Saturday, 23 January 2016

Spring Bean Life Cycle is managed by Spring Container.
Spring beans are eagerly initialised, as ApplicationContext object is created:

ApplicationContext appContext1=new ClassPathXmlApplicationContext("beans.xml");

Beans are instantiated and wired as per defined configuration in xml or annotations.
Spring container provides callback methods as customization points in order to add customizations in a bean.

Few important interfaces to add customization to a bean:

1. BeanFactoryPostProcessor- Operates on bean configuration metadata.The Spring IoC container allows a BeanFactoryPostProcessor to read the configuration metadata and potentially change it before the container instantiates any beans other than BeanFactoryPostProcessors.

Example:
PropertyPlaceholderConfigurer: subclass that resolves ${...} placeholders against local properties and/or system properties and environment variables.

2. BeanPostProcessor - The org.springframework.beans.factory.config.BeanPostProcessor interface consists of exactly two callback methods. When such a class is registered as a post-processor with the container, for each bean instance that is created by the container, the post-processor gets a callback from the container both before container initialization methods (such as InitializingBean’s afterPropertiesSet() and any declared init method) are called as well as after any bean initialization callbacks.

Spring Framework Class Examples:
PersistenceAnnotationBeanPostProcessor: BeanPostProcessor that processes PersistenceUnit and PersistenceContext annotations, for injection of the corresponding JPA resources EntityManagerFactory and EntityManager. Any such annotated fields or methods in any Spring-managed object will automatically be injected.
RequiredAnnotationBeanPostProcessor: implementation that enforces required JavaBean properties to have been configured.

3. InitializingBean and DisposableBean- The org.springframework.beans.factory.InitializingBean interface allows a bean to perform initialization work after all necessary properties on the bean have been set by the container.
Implementing the org.springframework.beans.factory.DisposableBean interface allows a bean to get a callback when the container containing it is destroyed.

4. ApplicationContextAware and BeanNameAware: When an ApplicationContext creates an object instance that implements the org.springframework.context.ApplicationContextAware interface, the instance is provided with a reference to that ApplicationContext.

When an ApplicationContext creates a class that implements the org.springframework.beans.factory.BeanNameAware interface, the class is provided with a reference to the name defined in its associated object definition.



5. FactoryBean: The FactoryBean interface is a point of pluggability into the Spring IoC container’s instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean, write the complex initialization inside that class, and then plug your custom FactoryBean into the container.
Link for FactoryBean Example:


Important methods to add customization to bean:
1. init-method:Called after a bean is initialised and it's properties are set.

     <bean id="class10" class="com.application.bl.Class10" init-method="init">
          <property name="studentDao" ref="studentDAO"></property>
      </bean>

Now com.application.bl.Class10 can define a init() method to add customizations.



2. destroy-method: Called before a bean is destroyed.

      <bean id="class10" class="com.application.bl.Class10" destroy-method="destroy">
         <property name="studentDao" ref="studentDAO"></property>
      </bean>
Now com.application.bl.Class10 can define a destroy() method to add customizations.

Annotations for above methods: @PostConstruct and @PreDestroy respectively.

BeanFactory vs ApplicationContext:

Bean initialization process in a glance:

public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}
}
}

Useful Links: