Wednesday, November 3, 2010

Spring Bean Life Cycle Phases

I want to demonstrate the bean Life Cycle with a help of a simple Example.

Phase 1. BeanPostProcessor: Bean definitions are changes here.

[Example : Property file replacement as property values.]

Phase 2: Object Creation Phase

Phase 3 :Setting Required Dependencies

Phase 4: Initialization Phase


There is a separate phase called BeanPostProcessor phase in which there the bean itself can be changes.

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 (see below for how this registration is effected), for each bean instance that is created by the container, the post-processor will get a callback from the container both before any container initialization methods (such as afterPropertiesSet and any declared init method) are called, and also afterwards. The post-processor is free to do what it wishes with the bean instance, including ignoring the callback completely.

Spring uses runtime AOP and hence creates proxy based implementation using this phase.
Since AOP auto-proxying is implemented as a BeanPostProcessor itself, no BeanPostProcessors
or directly referenced beans are eligible for auto-proxying (and thus will not have aspects 'woven' into them.

In my sample example i will not be talking about BeanFactoryPostProcessorPhase or BeanPostProcessor instaed will be concentrating on the phases.

Consider teh following three simple classes.



public class Bean1{

private Bean2 bean2;

private Bean3 bean3;

public void setBean3(Bean3 bean3) {
this.bean3 = bean3;
System.out.println("Setter Called For bean3");
}


public Bean1(Bean2 bean2) {
super();
this.bean2 = bean2;
System.out.println("Bean 1 constructor called");
}

public void init() {
System.out.println("Init of bean1 method called");
}

}






public class Bean2 {

private Bean1 bean1;

public Bean2() {
super();
System.out.println("Bean2 constructior Called");
}

public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
System.out.println("Setter Called");
}

public void init() {
System.out.println("Init of bean2 method called");
}

}






public class Bean3 {

public Bean3() {
super();
System.out.println("Construictor Called for Bean3");
}

private Bean1 bean1;

public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
System.out.println("Setter for Bean1 Called in Bean3");
}

public void init() {
System.out.println("Init Called For Bean3");
}

}




The spring xml will be as follows



<bean id="bean1" class="com.test.Bean1" init-method="init">
<constructor-arg ref="bean2"></constructor-arg>
<property name="bean3" ref="bean3"></property>
</bean>

<bean id="bean2" class="com.test.Bean2" init-method="init">
</bean>

<bean id="bean3" class="com.test.Bean3" init-method="init">
<property name="bean1" ref="bean1"></property>
</bean>




OutPut :

Bean2 constructior Called
Init of bean2 method called
Bean 1 constructor called
Construictor Called for Bean3
Setter for Bean1 Called in Bean3
Init Called For Bean3
Setter Called For bean3
Init of bean1 method called

Let me explain how this workz

Phase 2: Object Creation Phase
Phase 3: Initialization Phase
Phase 4: Setting Required Dependencies


bean1 : Phase2(started) - Tries to create object.Since the constructor requires bean2 goes to beans 2

bean2 : Phase2(started->completed) - Creates teh object(Hence sysout from constructor)
bean2 : Phase3(started->completed) - Nothing to be done as no property setters are present
bean2 : Phase4(started->completed) - Calls init method(As there are no property values to be Set)

bean1 : Phase2(completed) - Since beans 2 is ready this phase will complete(constructor sysout printed)
bean2 : Phase3(started) - Checks for dependency and finds bean3

bean3 : Phase2(started->completed) - Creates teh object(Hence sysout from constructor)
bean3 : Phase3(started->completed) - Sets the dependencies. [******** beans 3's init is called b4 bean1's init]
bean3 : Phase4(started->completed) - Init method called.

bean1 : Phase3(started->completed) - Setters called
bean1 : Phase4(started->completed) - Init Method called.


Hence all the beans go through these individual life cycle methods.

The following is the ordering for initialization methods based on the approach followed for initializing:
[All these are part of Phase4 above]
• Methods annotated with @PostConstruct
• afterPropertiesSet() as defined by the InitializingBean callback interface
• A custom configured init() method


In all the cases spring tries to ensure that before dependencies(beans) are set , the dependency(bean) is properly initialized.(dependency set and init called). {**** -Not always true for simple property injection - i. e before bean is injected its(injected bean) init may not have been called }

This is strict for Constructor injection.[In the above case if we try to modify the bean definition for bean 3 as follows]

<bean id="bean2" class="com.test.Bean2" init-method="init">
<property name="bean1" ref="bean1"></property>
</bean>


We get the following Exception

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bean1': Requested bean is currently in creation: Is there an unresolvable circular reference?


This is because bean1's constructor depends on bean2. and bean2 has a setter which is bean1. Bean2 just after completing phase 2(object creation will not be injected into constructor , will wait for all phases to complete)

***** - But this is not the case with simple property injected.

Ex : Bean1 and Bean 2 injected visa versa will work fine.

No comments:

 
Free Domain Names @ .co.nr!