Recently, I am relearning the excellent framework of spring. By the way, I will record my summary and share it with you. The bean life cycle refers to the process of bean creation - > initialization - > destruction. The bean life cycle is managed by the container. We can customize the bean initialization and destruction methods to meet our needs. When the container reaches the current life cycle of the bean, it will call the customized initialization and destruction methods. Today, I will mainly explain how to define the four methods of initialization and destruction.
1. Use initMethod and destroyMethod
The following code is all through the configuration class, not the configuration xml file
Train.java
package cap5.bean; public class Train { public Train() { // TODO Auto-generated constructor stub super(); System.out.println("Train establish"); } public void init() { System.out.println("train init..."); } public void destroy() { System.out.println("train destroy"); } }
MainConfig.java
package cap5.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ComponentScan.Filter; import cap5.bean.Bike; import cap5.bean.Jeep; import cap5.bean.TaolongBeanPostProcessor; import cap5.bean.Train; //@ComponentScan(value= {"cap5.bean"},includeFilters= {@Filter(type=FilterType.ASSIGNABLE_TYPE,classes=TaolongBeanPostProcessor.class)}) @Configuration public class MainConfig { @Bean(initMethod="init",destroyMethod="destroy") public Train train() { return new Train(); } /*@Bean public Bike bike() { return new Bike(); }*/ /*@Bean public Jeep jeep() { return new Jeep(); }*/ }
MainTest.java
package cap5.test; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import cap5.config.MainConfig; public class MainTest { @Test public void test() { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class); System.out.println("IOC Container creation complete"); System.out.println("IOC Easy ready to close"); /*String[] names = app.getBeanDefinitionNames(); for(String name:names) { System.out.println("name="+name); }*/ app.close(); } }
Print results:

2. Let the bean implement the InitializingBean and DisposableBean interfaces, and then implement the afterpropertieset () method and destroy () method respectively
afterPropertiesSet(): it can be seen from the name that this is not the real initialization method of bean, but the method called after the completion of bean and the setting of the attributes - the function is equivalent to the initialization method.
destroy(): when the bean is destroyed, the single instance bean will be destroyed
Bike.java
package cap5.bean; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; public class Bike implements InitializingBean,DisposableBean{ public Bike() { // TODO Auto-generated constructor stub super(); System.out.println("bike construct..."); } public void destroy() throws Exception { // TODO Auto-generated method stub System.out.println("bike destroy"); } public void afterPropertiesSet() throws Exception { // TODO Auto-generated method stub System.out.println("bike init..."); } }
MainConfig.java
package cap5.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ComponentScan.Filter; import cap5.bean.Bike; import cap5.bean.Jeep; import cap5.bean.TaolongBeanPostProcessor; import cap5.bean.Train; //@ComponentScan(value= {"cap5.bean"},includeFilters= {@Filter(type=FilterType.ASSIGNABLE_TYPE,classes=TaolongBeanPostProcessor.class)}) @Configuration public class MainConfig { /*@Bean(initMethod="init",destroyMethod="destroy") public Train train() { return new Train(); }*/ @Bean public Bike bike() { return new Bike(); } /*@Bean public Jeep jeep() { return new Jeep(); }*/ }
MainTest.java is the same as the above, so it won't be posted anymore
Test results:

3. Use the annotation defined by the JSR250 rule to realize it. You can learn more about JSR250 by yourself. The following two annotations are mainly used
@PostConstruct: you can see from the name that the meaning of this annotation is that after the completion of bean construction, it is equivalent to initialization.
@PreDestroy: it can also be seen from the name that it is an annotated method that will be executed before beandestroy - equivalent to destruction
Jeep.java
package cap5.bean; import javax.annotation.*; public class Jeep { public Jeep() { // TODO Auto-generated constructor stub super(); System.out.println("jeep construct..."); } @PostConstruct public void init() { System.out.println("jeep init..."); } @PreDestroy public void destroy() { System.out.println("jeep destroy..."); } }
MainConfig.java
package cap5.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ComponentScan.Filter; import cap5.bean.Bike; import cap5.bean.Jeep; import cap5.bean.TaolongBeanPostProcessor; import cap5.bean.Train; //@ComponentScan(value= {"cap5.bean"},includeFilters= {@Filter(type=FilterType.ASSIGNABLE_TYPE,classes=TaolongBeanPostProcessor.class)}) @Configuration public class MainConfig { /*@Bean(initMethod="init",destroyMethod="destroy") public Train train() { return new Train(); }*/ /*@Bean public Bike bike() { return new Bike(); }*/ @Bean public Jeep jeep() { return new Jeep(); } }
MainTest.java is the same as above. Don't paste it again
Operation results:

4. The fourth method is to use the post processor. Before and after bean initialization, it will call and implement the BeanPostProcessor interface and rewrite the two methods: postProcessBeforeInitialization() and postProcessAfterInitialization()
TaolongBeanPostProcessor.java
package cap5.bean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class TaolongBeanPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("bean-----"+beanName+" init start..."); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("bean------"+beanName+" init end..."); return bean; } }
Plane.java
package cap5.bean; public class Plane { public Plane() { // TODO Auto-generated constructor stub System.out.println("plane construct..."); } }
MainConfig.java
package cap5.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ComponentScan.Filter; import cap5.bean.Bike; import cap5.bean.Jeep; import cap5.bean.Plane; import cap5.bean.TaolongBeanPostProcessor; import cap5.bean.Train; //@ComponentScan(value= {"cap5.bean"},includeFilters= {@Filter(type=FilterType.ASSIGNABLE_TYPE,classes=TaolongBeanPostProcessor.class)}) @Configuration public class MainConfig { /*@Bean(initMethod="init",destroyMethod="destroy") public Train train() { return new Train(); }*/ /*@Bean public Bike bike() { return new Bike(); }*/ /*@Bean public Jeep jeep() { return new Jeep(); }*/ @Bean public Plane plane() { return new Plane(); } @Bean public TaolongBeanPostProcessor taolongBeanPostProcessor() { return new TaolongBeanPostProcessor(); } }
Test effect:

The above are all single instance bean patterns by default. How about adding multiple beans? How does the container manage the bean lifecycle?
(1) When the bean is in the multi instance mode, the bean will not be instantiated when the IOC container is created, but when the bean is actually used. This can be tested simply. When @ scope ("prototype") is added, the bean is created by multiple instances
(2) When the container is closed, how to deal with multiple instances? Will multiple instances be destroyed at the same time?
Let's simply test:
MainConfig.java partial code
@Scope("prototype") @Bean public Bike bike() { return new Bike(); }
MianTest.java
package cap5.test; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import cap5.bean.Bike; import cap5.config.MainConfig; public class MainTest { @Test public void test() { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class); System.out.println("IOC Container creation complete"); Bike bike1 = (Bike)app.getBean(Bike.class); Bike bike2 = (Bike)app.getBean(Bike.class); System.out.println(bike1==bike2); System.out.println("IOC Easy ready to close"); /*String[] names = app.getBeanDefinitionNames(); for(String name:names) { System.out.println("name="+name); }*/ app.close(); } }
Operation results:

This result confirms the problem
1. In the case of multiple instances, the bean will not be created with the construction of IOC container, but the getBean() created when it is used
2. In the case of multiple instances, when the container is closed, the bean instance will not call the destroy method, indicating that the container does not control the destruction of multiple instances
3. In the case of multiple instances, if the returned bean objects are different, the return is false