1. El ciclo de vida de un bean.
Como anteriormente se pudo ver, Spring, gestiona el ciclo de vida del bean durante toda su ejecución, la cual se basa en tres etapas; ,la inicialización, el uso, y la destrucción.
- Inicialización: Los servicios de la aplicación son creados, configurados y se pueden asignar recursos del sistema.
- Uso: En esta esta se procesan las peticiones de los clientes, los comportamientos de la aplicación son llevados acabo en esta etapa, siendo esta la que ocupa la mayor parte del tiempo del ciclo de vida.
- Destrucción: En la destrucción se liberan los recursos del sistema mediante el garbage colletion.
2. Fases:
2.1 Inicialización:
2.1.1 Carga de la definición de Beans
¿Que pasa cuando se instancia un ApplicacionContext?
ApplicationContext context = new ClassPathXmlApplicationContext(“basic-context.xml”);
La fase de inicialización esta completa cuando se crea el contexto, en esta etapa se parsean el o los archivos xml de configuración , las definiciones de los beans son cargados en el contexto del BeanFactory, como anteriormente se menciono, estos se crean con un identificador único, para el contexto, luego, se invocan a clases y métodos especiales que nos permiten modificar las definiciones de los beans que fueron creados anteriormente, esta funcion la realizan los beans del tipo BeanFactoryPostProcessor, los cual nos permiten manipular, transformar grupos de definiciones de beans antes que los objetos sean creados, podemos incluso crear nuestras propias implementaciones de esta interfaz.
Clases que implementan BeanFactoryPostProcesor en Spring 2.5
AspectJWeavingEnabler, CustomAutowireConfigurer, CustomEditorConfigurer, CustomScopeConfigurer,
PreferencesPlaceholderConfigurer, PropertyOverrideConfigurer, PropertyPlaceholderConfigurer,
PropertyResourceConfigurer, ServletContextPropertyPlaceholderConfigurer
Un ejmeplo de una clase que implementa BeanFactoryPostProcessor es la clase PropertyPlaceholderConfigurer, que nos permite substituir valores de variables para los beans desde archivos de configuración, ejemplo tenemos un archivo datasource.properties que contiene la forma clave=valor como la siguiente entrada:
driver=com.mysql.jdbc.Driver dbname=mysql:mydb
Para cargar las propiedades del archivo, se tiene que usar la sintaxis del placeholder
{...}
como en el siguiente ejemplo, que crea un data source, en donde los … serán reemplazados por las claves de nuestra configuración, en este caso, driver y dbname.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"><value>${driver}</value></property> <property name="url"><value>jdbc:${dbname}</value></property> </bean>
para poder leer y cargar el archivo, spring entre otros, nos proporciona, prefijos para los namespace de configuración que nos facilita el trabajo, uno de estos es el <context>.
<context:property-placeholder location=“/WEB-INF/datasource.properties” />
2.1.2 Inicialización de la instancia del Bean
- Cada bean, es instanciado en forma temprana, es creado en el orden correcto con la inyección de sus dependencias.
- Después de la inyección de dependencias, los beans pasan a una etapa de post procesamiento, luego de esta etapa, están inicializados y listos para ser usados.
La etapa del post procesamiento se puede separar en dos, se le puede ordenar inicializar la instancia del bean,o se puede implementar un BeanPostProcessors, que nos permite modificar de una manera personalizada las nuevas instancias de los beans.
Si queremos ejecutar comportamientos específicos o invocar métodos que necesitemos en la instanciación de bean, spring nos proporciona mas de una manera para poder hacerlo; mediante la anotación de la JSR-250 @PostConstruct, o a través del init-method, en el cual se especifica el nombre del método inicial que se ejecutará durante la instanciación del bean, esto se realiza en el archivo de configuración de Spring, y una tercera opción, es implementando la interfaz InitializingBean.
Vía Anotación:
package com.spring.basic.initialization; import javax.annotation.PostConstruct; public class SimpleBeanImpl { @PostConstruct void initMehtod(){ //metodo a inicial que es ejecutado despues de que //la inyeccion de dependencias haya finalizado } }
* esto es para Spring 2.5 o superior
Para habilitar esta característica, debemos agregar en el archivo de configuración el bean CommonAnnotationBeanPostProcessor o lo recomendado es usar el namespace <context:annotation-config/> , solo bastan con agregarlo tal cual.
Mediante el init-method:
El método debe ser publico, y el bean no debe tener dependencias.
<bean id="simpleBean" class="com.spring.basic.initialization.SimpleBeanImpl" init-method="initMehtod"/>
y mediante la implementación de InitializingBean:
Para versiones inferiores a spring 2.5, es recomendable usar esta implementación, para versiones superiores o igual a la 2.5, se recomienda usar @PostConstruct.
package ... import org.springframework.beans.factory.InitializingBean; public class SimpleBeanImpl implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { // para versiones inferiores a spring 2.5 } }
El método afterPropertiesSet() es invocado automáticamente por Spring.
La interfaz BeanPostProcessor nos permite llevar a cabo configuraciones adicionales, entre sus funciones, nos permite modificar la instancia de un bean en cualquier momento, spring detecta automáticamente estos tipos de beans, los podemos usar para trabajar con proxies, o para marcar algunas interfaces de modo que la inyección sea requerida, como lo proporciona la anotación @Required, para habilitar esta opción, solo basta agregar <context:annotation-config/> a la configuración.
La interfaz nos provee de dos métodos para poder modificar las instancias, el primero de ellos, es el postProcessAfterInitialization, que nos retorna una nueva instancia después de que se haya hecho la llamada de inicialización, y el otro método, postProcessBeforeInitialization, quien lo realiza antes de la llamada de instanciación.
Existe una implementación de BeanPostProcessor llamada RequiredAnnotationBeanPostProcessor que nos permite verificar en tiempo de configuración que todas las propriedades marcadas con la anotación @Required estén seteadas correctamente, si no usamos esta verificación, no nos daríamos cuenta hasta usar el bean que su dependencia no fue inyectada.
... private DataSource dataSource; /** * Set del datasource * @param dataSource the data source */ @Required public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; }
Vía Anotación:
public class SimpleBeanImpl { @PreDestroy void release(){ //se llama antes que se realize la destruccion de la instancia del bean //sin restriccion del nombre del metodo ni de visibilidad } }
Mediante el destroy-method:
El método debe ser publico, y el bean no debe tener dependencias, ni argumentos
<bean id="simpleBean" class="...SimpleBean" destroy-method="release"/>
*el método debe ser publico y no debe tener dependencias.
Mediante la implementación de DisposableBean:
public class SimpleBeanDestroy implements DisposableBean { @Override public void destroy() throws Exception { //sping se encarga de llamar a este método en el momento adecuado } }