Bean life cycle
Compared with the life cycle of beans created by ourselves, they are instantiated through the new keyword and recycled when they are no longer used. The life cycle of beans in the Spring container is more complex. Let's take a look at the following bean life cycle diagram.
As a supplement to the above figure, there should be another step between BeaFactoryAware's setBeanFactory() and pre initialization beanpostprocessor: call the setApplicationContext() method of ApplicationContextAware.
As can be seen from the above figure, the Bean life cycle goes through many stages, but most of these stages are optional. For example, if a Bean implements the setBeanFactory method of the BeanFactoryAware interface, the life of the Bean will go through this stage. If it is not implemented, it will not.
Let's take a look at how to implement a bean that has gone through all the above life cycle stages
First define the Bean object and implement the following interfaces
- BeanNameAware
- BeanFactoryAware
- ApplicationContextAware
- InitializingBean
- DisposableBean
@Component public class Car implements BeanNameAware,BeanFactoryAware, ApplicationContextAware,InitializingBean,DisposableBean { //Seat is also a simple bean object private Seat seat; public Car(){ System.out.println("car instance..."); } public Seat getSeat() { return seat; } @Autowired public void setSeat(Seat seat) { System.out.println("Fill properties"); this.seat = seat; } // Custom initialization method public void init(){ System.out.println("car ... init..."); } // Custom destruction method public void detory(){ System.out.println("car ... detory..."); } @Override public void setBeanName(String s) { System.out.println(s); System.out.println("BeanNameAware...setBeanName()"); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("DisposableBean...setBeanFactory()"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("ApplicationContextAware...setApplicationContext()"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean...afterPropertiesSet()"); } @Override public void destroy() throws Exception { System.out.println("InitializingBean...destroy()"); } }
After you have customized initialization methods and destruction methods, you need to configure them. You can specify them in the configurator class through @ bean (initmethod = "init", destroymethod = "destroy"), or directly add @ PostConstruct or @ PreDestroy annotations to the methods
//After the object is created and assigned, it is called. @PostConstruct public void init(){ System.out.println("car....@PostConstruct..."); } //Before removing objects from the container @PreDestroy public void detory(){ System.out.println("car....@PreDestroy..."); }
Then define a post processor of the Bean: BeanPostProcessor
@Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization..."+beanName+"..."+bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization..."+beanName+"..."+bean); return bean; } }
Finally, write a test class and observe the running results
@Test public void test(){ //1. Create ioc container AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); System.out.println("Container creation complete..."); applicationContext.getBean("car"); //Close the container applicationContext.close(); }
The output result is:
car instance... Fill properties BeanNameAware...setBeanName() DisposableBean...setBeanFactory() ApplicationContextAware...setApplicationContext() postProcessBeforeInitialization...car...cn.zgc.spring.annotation.beans.Car@22b49166 InitializingBean...afterPropertiesSet() car ... init... postProcessAfterInitialization...car...cn.zgc.spring.annotation.beans.Car@22b49166 Container creation complete... InitializingBean...destroy() car ... detory...
Viewing the output results, you can see that the life cycle of Car is consistent with the figure above
##Life cycle construction principle
Let's take a look at how it is implemented in the Spring source code. Let's make a breakpoint in the custom Bean post processor MyBeanPostProcessor to see the method call stack
Here's a reminder. It's cumbersome to look at the source code of Spring. It's easy to get caught up in the details. Therefore, we should grasp the key code and sort out the overall context, and we shouldn't and don't miss the details too much
Here, we mainly take a look at the doCreateBean method of AbstractAutowireCapableBeanFactory, in which there is such a piece of code
//Instantiate bean s if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = this.createBeanInstance(beanName, mbd, args); } ...... try { // Populate the properties of the bean this.populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = this.initializeBean(beanName, exposedObject, mbd); } }
Continue to see what is done in the initializeBean method
// The callback implements the methods in the xxxAware interface this.invokeAwareMethods(beanName, bean); ...... // Call the postProcessorsBeforeInitialization method of BeanPostProcessor wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName); ...... try { //Call the initialization method (custom initialization method or implement the initializingbean interface) invokeInitMethods(beanName, wrappedBean, mbd); }catch (Throwable ex) { .... } if (mbd == null || !mbd.isSynthetic()) { // Call the postProcessorsAfterInitialization method of BeanPostProcessor wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
Next, combined with the source code, the life cycle process of Bean is given in the form of pseudo code, but it does not include two destruction stages
// Create Bean new Bean(); // Assign properties to bean s populateBean(beanName, mbd, instanceWrapper); // Here is a series of operations on bean s initializeBean() { applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); invokeInitMethods(beanName, wrappedBean, mbd);Perform custom initialization { if(bean instanceof InitializingBean){ ((InitializingBean) bean).afterPropertiesSet(); } if(mbd.getInitMethodName()!=null){ //Custom initialization method execution invokeCustomInitMethod(beanName, bean, mbd); } } applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
Summary
In Spring, the life cycle of a bean is a long process, with many steps, and each step can control the bean. Understanding this process is very helpful for us to read the Spring source code and expand Spring.