The lifecycle of a Spring bean

In this blogpost, I’ll talk and give a few examples of the lifecycle of a bean in a Spring container.
The examples are tested with Spring 3.0RC1 but should work with Spring 2.5+
Xml Attributes
In this first example, I’ll show you how the lifecycle of a bean happens within the xml-configfile.
In the xml-file, we can define an init- and destroy-method to the bean, which will be called automatically by Spring.
Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="attributesTest" class="a.Test" init-method="initMethod" destroy-method="destroyMethod">
</bean>
</beans>
Main program
In this case, I’ll use AbstractApplicationContext because this Context has a function to destroy the Context which a normal ApplicationContext doesn’t have.
package a;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class XmlAttributesTest {
public static void main(String[] args) {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("Config.xml");
ctx.registerShutdownHook();
Test test = ctx.getBean("attributesTest",Test.class);
}
}
Test.java
package a;
public class Test{
public Test(){
System.out.println("We are in the constructor of Test");
}
public void initMethod(){
System.out.println("We are in initMethod of Test");
}
public void destroyMethod(){
System.out.println("We are in destroyMethod of Test");
}
}
The output will be:
We are in the constructor of Test We are in initMethod of Test We are in destroyMethod of Test
It’s also possible to declare default init- and destroy-methods in the xml-file. This is done in the beans-tag:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-init-method="initMethod"
default-destroy-method="destroyMethod">
...
LifeCycles with interfaces
It’s possible to call the lifecyclemethods by implemnting a Spring interface.
It’s very easy to do but I don’t recommend this because when you use the interfaces, your code will be highly coupled to the Spring Framework which isn’t always a good case.
Config.xml
You don’t have to set an init and destroy method in the xml-file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="interfacesTest" class="b.Test">
</bean>
</beans>
Main program
This is always the same…
package b;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class InterfaceTest {
public static void main(String[] args) {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("Config.xml");
ctx.registerShutdownHook();
Test test = ctx.getBean("interfacesTest",Test.class);
}
}
Test.java
We have to implement InitializingBean for init-methods and DisposableBean for destroy-methods
package b;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Test implements InitializingBean, DisposableBean {
public Test(){
System.out.println("We are in the constructor of Test");
}
public void afterPropertiesSet() throws Exception {
System.out.println("We are in afterPropertiesSet of Test");
}
public void destroy() throws Exception {
System.out.println("We are in destroy of Test");
}
}
Lifecycle with annotations
Config.xml
Don’t forget to include to enable annotations with the Contextparameters in the xml-file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean id="annotationsTest" class="c.Test">
</bean>
</beans>
Main program
Still the same…
package c;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationsTest {
public static void main(String[] args) {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("Config.xml");
ctx.registerShutdownHook();
Test test = ctx.getBean("annotationsTest", Test.class);
}
}
Test.java
We can use the lifecyclemethods with the annotations @PostConstruct for init-methods and @PostDestroy for destroy-methods.
package c;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Test {
public Test() {
System.out.println("We are in the constructor of Test");
}
@PostConstruct
public void start(){
System.out.println("We are in the start-method of Test");
}
@PreDestroy
public void stop(){
System.out.println("We are in the stop-method of Test");
}
}
Putting them all together
It’s possible to use the 3 methods all together
Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean id="allTogether" class="d.Test" init-method="initMethod" destroy-method="destroyMethod">
</bean>
</beans>
Main program
package d;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AllTogetherTest {
public static void main(String[] args) {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("Config.xml");
ctx.registerShutdownHook();
Test test = ctx.getBean("allTogether", Test.class);
}
}
Test.java
We are using interfaces AND annotations.
It’s even possible to use multiple times the same annotation:
package d;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Test implements DisposableBean,InitializingBean {
public void destroy() throws Exception {
System.out.println("DisposableBean-Interface");
}
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean-Interface");
}
@PostConstruct
public void start(){
System.out.println("First PostConstruct");
}
@PostConstruct
public void start2(){
System.out.println("Second PostConstruct");
}
@PostConstruct
public void start3(){
System.out.println("Third PostConstruct");
}
@PreDestroy
public void stop(){
System.out.println("PreDestroy");
}
public void initMethod(){
System.out.println("initMethod");
}
public void destroyMethod(){
System.out.println("destroyMethod");
}
}
The output is:
Third PostConstruct Second PostConstruct First PostConstruct InitializingBean-Interface initMethod PreDestroy DisposableBean-Interface destroyMethod
So we can conclude that the annotations are processed first, followed by the interfaces and at last the methods from the xml-file.