Spring IoC container is also responsible for managing the Spring Bean Life Cycle, the life cycle of beans consist of call back methods such as Post initialization call back method and Pre destruction call back method. Below steps are followed by Spring IoC Container to manage bean life cycle.
Spring Bean Life Cycle
- The Bean Container finds the definition of the Spring Bean in the Configuration file
- The Bean Container creates an instance of the Bean using Java Reflection API.
- If any properties are mentioned, then they are also applied. If the property itself is a Bean, then it is resolved and set.
- Call the initialization call back method.
- Bean is ready for use.
- Call the destruction call back method.
Spring can recognize the initialization and destruction callback methods in the below three ways.
- A Bean can implement the InitializingBean and DisposableBean life cycle interfaces and overriding the afterPropertiesSet() (Called during Spring bean initialization) and destroy() methods for initialization and destruction respectively.
- Set the init-method and destroy-method attributes in the bean configuration file.
- Use @PostConstruct and @PreDestroy over the methods (Spring 2.5 or later).
Using InitializingBean and DisposableBean
beanConfig.xml
HelloBean.java
package com.spring.example.bean;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class HelloBean implements InitializingBean, DisposableBean {
private String testProperty;
public HelloBean() {
System.out.println(“HelloBean no-args constructor called”);
}
@Override
public void destroy() {
System.out.println(“HelloBean destroy method called”);
}
public String getTestProperty() {
return testProperty;
}
public void setTestProperty(String testProperty) {
this.testProperty = testProperty;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(“HelloBean init method called”);
}
}
TestBeanLifeCycle
package com.spring.example.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.example.bean.HelloBean;
public class TestBeanLifeCycle {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
“beanConfig.xml”);
HelloBean helloBean = (HelloBean) context.getBean(“helloBean”);
System.out.println(helloBean.getTestProperty());
context.close();
}
}
Output
HelloBean no-args constructor called
HelloBean init method called
test
HelloBean destroy method called
Note:This approach is simple to use but it’s not recommended because it will create tight coupling with the Spring framework in our bean implementations.
Using init-method and destroy-method attributes
beanConfig.xml
HelloBean.java
package com.spring.example.bean;
public class HelloBean {
private String testProperty;
public void init(){
System.out.println(“HelloBean init method called”);
}
public HelloBean(){
System.out.println(“HelloBean no-args constructor called”);
}
public void destroy(){
System.out.println(“HelloBean destroy method called”);
}
public String getTestProperty() {
return testProperty;
}
public void setTestProperty(String testProperty) {
this.testProperty = testProperty;
}
}
TestBeanLifeCycle
package com.spring.example.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.example.bean.HelloBean;
public class TestBeanLifeCycle {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
“beanConfig.xml”);
HelloBean helloBean = (HelloBean) context.getBean(“helloBean”);
System.out.println(helloBean.getTestProperty());
context.close();
}
}
Output
HelloBean no-args constructor called
HelloBean init method called
test
HelloBean destroy method called
Using @PostConstruct and @PreDestroy
BeanConfiguration.java
package com.spring.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.spring.example.bean.HelloBean;
@ComponentScan(basePackages = “com.spring.example.bean”)
@Configuration
public class BeanConfiguration {
@Bean
public HelloBean helloBean() {
HelloBean helloBean = new HelloBean();
helloBean.setTestProperty(“test”);
return helloBean;
}
}
HelloBean.java
package com.spring.example.bean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class HelloBean {
private String testProperty;
@PostConstruct
public void init(){
System.out.println(“HelloBean init method called”);
}
public HelloBean(){
System.out.println(“HelloBean no-args constructor called”);
}
@PreDestroy
public void destroy(){
System.out.println(“HelloBean destroy method called”);
}
public String getTestProperty() {
return testProperty;
}
public void setTestProperty(String testProperty) {
this.testProperty = testProperty;
}
}
TestBeanLifeCycle.java
package com.spring.example.test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.spring.example.bean.HelloBean;
import com.spring.example.config.BeanConfiguration;
public class TestBeanLifeCycle {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
HelloBean helloBean = context.getBean(HelloBean.class);
System.out.println(helloBean.getTestProperty());
context.close();
}
}
Output
HelloBean no-args constructor called
HelloBean init method called
test
HelloBean destroy method called