BeanPostProcessor
En el capítulo ciclo de vida de bean, revisamos algunos mecanismos que nos provee Spring para ejecutar tareas después de inicilizar un bean y antes de la destrucción del mismo. Estos mecanismos nos permitían configurar las propiedades del bean (no la instancia como tal).
Pero que sucede si se desea personalizar el tipo de instancia del bean (el tipo de clase) creada por el contenedor. Para esta tarea Spring provee la interfaz BeanPostProcessor, a través de la cual vamos a poder cambiar la lógica de creación y las propiedades del bean que fueron configuradas por el contenedor previamente.
BeanPostProcessor define los métodos postProcessBeforeInitialization() y postProcessAfterInitialization() que son llamados por cada instancia creada por el contenedor.Es decir, cada vez que el contenedor Spring crea, configura y ensambla un bean, la instancia de BeanPostProcessor trabaja sobre ese bean.
Tenga presente que postProcessBeforeInitialization() es llamado antes de los métodos de inicio propios del bean(InitializingBean o init), mientras que postProcessAfterInitialization() después de cualquier devolución de llamada de inicialización de bean.
Las instancias de BeanPostProcessor de define como cualquier otro bean del contenedor Spring, son creados en el inicio como parte de la fase de inicio especial del contenedor.
Ejemplo
Vamos a replicar el ejemplo realizado en inyección de depencias I que consistía en crear los beans miEsfero y tinta, donde tinta era una dependencia de esfero.
Objetivo
Utilizaremos un BeanPostProcessor para comprobar si al bean miEsfero se le asigno una tinta, si no es caso, le asignaremos una tinta por defecto.
Contenedor Spring
En el contenedor simplemente dejamos la definición del bean miEsfero, añadimos un constructor vacio a la clase Esfero(obligatorio).
<bean id="miEsfero" class="com.curso.spring.Esfero"> </bean>
Con esta configuración, al bean miEsfero no se le asignado ninguna tinta todavía, si ejecuta TestEsfero, podrá notar que ocurre un error de tipo java.lang.NullPointerException.
Clase CustomBeanPostProcessor
Creamos la clase CustomBeanPostProcessor e implementamos la interfaz BeanPostProcessor, aquí verificaremos si el bean miEsfero se le fue asignado una tinta.
public class CustomBeanPostProcessor implements BeanPostProcessor{ /** * Método llamado por cada bean creado por el contenedor , recibe el bean y el nombre del bean. * Llamado antes de la inicialización del bean. Todas sus propiedades ya han sido asignadas. */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{ // Verificar que se este procesando el bean miEsfero if (beanName.equals("miEsfero")) { Esfero esfero = (Esfero) bean; // Verificar si tiene una tinta asignada if (esfero.getTinta() ==null) { // Crear una tinta Tinta tinta = new TintaNegra(); // Asignar tinta al esfero esfero.setTinta(tinta); // Otra alternativa a la anterior // ((Esfero) bean).setTinta(tinta); } } // Retornar bean return bean; } /** * Método llamado por cada bean creado por el contenedor, recibe el bean y el nombre del bean. * Llamado despues de la inicialización del bean. */ @Override public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException{ // Ejecutar tareas // Retornar bean return bean; } }
Bean CustomBeanPostProcessor
<bean class="com.curso.spring.CustomBeanPostProcessor"> </bean>
Descripción
Para el ejemplo, sobrescribimos solo el método postProcessBeforeInitialization(), primero validamos que el bean miEsfero sea el que se este procesando, lo hacemos a través del parametro beanName, recuerda que postProcessBeforeInitialization() es llamado para cada bean creado del contenedor, por ende, debemos asegurarnos de trabajar con la instancia del bean miEsfero, luego hacemos un casting de tipo para acceder a las propiedades de esfero, verificamos si el bean esfero tiene asignado una tinta, si no es así, le asignamos manualmente una
Prueba ahora la clase TestPersona y veras que se ejecuta correctamente.
Interfaz InstantiationAwareBeanPostProcessor
Si además de los callbacks de BeanPostProcessor, desea manejar callbacks antes y despúes de invocar al constructor o método de fabrica que instancia el bean, puede implementar la subintefaz InstantiationAwareBeanPostProcessor, está agrega los métodos postProcessBeforeInstantiation() y postProcessAfterInstantiation().
Comentarios
Publicar un comentario