As the most popular and powerful lightweight framework in Java, Spring has been warmly welcomed by programmers. It is very necessary to accurately understand the life cycle of Spring Bean. We usually use ApplicationContext as Spring container. Here, we are also talking about the life cycle of beans in ApplicationContext. In fact, BeanFactory is similar, but the processor needs to be manually registered.
1. Life cycle flow chart:
The full life cycle of a Spring Bean starts with creating a Spring container until the Spring container eventually destroys the Bean, which contains a series of key points.
If the container registers the above various interfaces, the program will be carried out according to the above process. The functions of each interface will be explained in detail below.
2. Classification of various interface methods
The full life cycle of a bean undergoes various method calls, which can be divided into the following categories:
1. Bean's own method: This includes the methods called by the Bean itself and the methods specified through the init-method and destroy-method in the configuration file.
2. Bean-level life cycle interface method: This includes interface methods such as BeanNameAware, BeanFactoryAware, InitializingBean and DiposableBean
3. Container-level life cycle interface method: This includes two interface implementations: InstantiationAwareBeanPostProcessor and BeanPostProcessor. Their implementation class is generally called "postprocessor".
4. Factory postprocessor interface method: This includes AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer and other very useful factory postprocessor interface methods. Factory postprocessors are also container-level. Called immediately after applying the context assembly configuration file.
3. Demo
Let's demonstrate the life cycle of Spring Bean with a simple Spring Bean.
1. First of all, it is a simple Spring Bean, which calls the Bean's own methods and Bean-level life cycle interface methods. For the sake of convenience of demonstration, it implements four interfaces: BeanNameAware, BeanFactoryAware, InitializingBean and DiposableBean. There are 2 methods at the same time, corresponding to the init-method and destroy-method of <bean> in the configuration file. as follows:
package springBeanTest;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.BeanNameAware;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;/** * @author qsk */public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean { private String name; private String address; private int phone; private BeanFactory beanFactory; private String beanName; public Person() { System.out.println("【Constructor】Call Person's constructor instantiation"); } public String getName() { return name; } public void setName(String name) { System.out.println("【Injection attribute】Injection attribute name"); this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { System.out.println("【Injection attribute】Injection attribute address"); this.address = address; } public int getPhone() { return phone; } public void setPhone(int phone) { System.out.println("【Injection attribute】Injection attribute phone"); this.phone = phone; } @Override public String toString() { return "Person [address=" + address + ", name=" + name + ", phone=" + phone + "]"; } // This is the BeanFactoryAware interface method @Override public void setBeanFactory(BeanFactory arg0) throws BeansException { System.out .println("【BeanFactoryAware interface】Call BeanFactoryAware.setBeanFactory()"); this.beanFactory = arg0; } // This is the BeanNameAware interface method @Override public void setBeanName(String arg0) { System.out.println("【BeanNameAware interface】Call BeanNameAware.setBeanName()"); this.beanName = arg0; } // This is the InitializingBean interface method @Override public void afterPropertiesSet() throws Exception { System.out .println("【InitializingBean Interface】Call InitializingBean.afterPropertiesSet()"); } // This is the DiposibleBean interface method @Override public void destroy() throws Exception { System.out.println("【DiposibleBean interface】Call DiposibleBean.destory()"); } // Initialization method specified through the init-method property of <bean> public void myInit() { System.out.println("【init-method】Call the initialization method specified by the init-method property of <bean>"); } // Initialization method specified by the destroy-method property of <bean> public void myDestory() { System.out.println("【destroy-method】Call the initialization method specified by the destroy-method property of <bean>"); }}2. Next is to demonstrate the method of the BeanPostProcessor interface, as follows:
package springBeanTest;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor { public MyBeanPostProcessor() { super(); System.out.println("This is the BeanPostProcessor implementation class constructor!!"); // TODO Auto-generated constructor stub } @Override public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException { System.out .println("BeanPostProcessor interface method postProcessAfterInitialization makes changes to the property!"); return arg0; } @Override public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException { System.out .println("BeanPostProcessor interface method postProcessBeforeInitialization changes the property!"); return arg0; }}As mentioned above, the BeanPostProcessor interface includes two methods postProcessAfterInitialization and postProcessBeforeInitialization. The first parameter of these two methods is the Bean object to be processed, and the second parameter is the name of the Bean. The return value is also the Bean object to be processed. Pay attention here.
3. The InstantiationAwareBeanPostProcessor interface is essentially a subinterface of BeanPostProcessor. Generally, we inherit the adapter class InstantiationAwareBeanPostProcessor Adapter provided by Spring to use it, as follows:
package springBeanTest;import java.beans.PropertyDescriptor;import org.springframework.beans.BeansException;import org.springframework.beans.PropertyValues;import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { public MyInstantiationAwareBeanPostProcessor() { super(); System.out .println("This is the InstantiationAwareBeanPostProcessorAdapter implementation class constructor!!"); } // Call @Override public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor calls postProcessBeforeInstantiation method"); return null; } // Interface method, call @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor calls postProcessAfterInitialization method"); return bean; } // Call @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor calls postProcessPropertyValues method"); return pvs; }}There are 3 methods for this, and the second method, postProcessAfterInitialization, is to rewrite the method of BeanPostProcessor. The third method, postProcessPropertyValues, is used to operate properties, and the return value should also be a PropertyValues object.
4. Demonstrate the factory postprocessor interface method, as follows:
package springBeanTest;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public MyBeanFactoryPostProcessor() { super(); System.out.println("This is the BeanFactoryPostProcessor implementation class constructor!!"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException { System.out .println("BeanFactoryPostProcessor calls postProcessBeanFactory method"); BeanDefinition bd = arg0.getBeanDefinition("person"); bd.getPropertyValues().addPropertyValue("phone", "110"); }}5. The configuration file is as follows beans.xml, which is very simple. When using ApplicationContext, the processor does not need to be manually registered:
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> <bean id="beanPostProcessor"> </bean> <bean id="instantiationAwareBeanPostProcessor"> </bean> <bean id="beanFactoryPostProcessor"> </bean> <bean id="person" init-method="myInit" destroy-method="myDestory" scope="singleton" p:name="Zhang San" p:address="Guangzhou" p:phone="15900000000" /></beans>
6. Test the following:
package springBeanTest;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanLifeCycle { public static void main(String[] args) { System.out.println("Start initialize the container now"); ApplicationContext factory = new ClassPathXmlApplicationContext("springBeanTest/beans.xml"); System.out.println("Container initialization successfully"); //Get Preson and use Person person = factory.getBean("person",Person.class); System.out.println(person); System.out.println(person); System.out.println("Start close the container now!"); ((ClassPathXmlApplicationContext)factory).registerShutdownHook(); }}Close the container using the hook method that is actually AbstractApplicationContext.
Let's take a look at the results:
Start initializing the container now 2014-5-18 15:46:20 org.springframework.context.support.AbstractApplicationContext prepareRefresh information: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@19a0c7c: startup date [Sun May 18 15:46:20 CST 2014]; root of context hierarchy2014-5-18 15:46:20 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions information: Loading XML bean definitions from class path resource [springBeanTest/beans.xml] This is the BeanFactoryPostProcessor implementation class constructor! ! BeanFactoryPostProcessor calls postProcessBeanFactory method This is the BeanPostProcessor implementation class constructor! ! This is the InstantiationAwareBeanPostProcessorAdapter implementation class constructor! ! 2014-5-18 15:46:20 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletonsInformation: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9934d4: defining beans [beanPostProcessor,instantiationAwareBeanPostProcessor,beanFactoryPostProcessor,person]; root of factory hierarchyInstantiationAwareBeanPostProcessor calls postProcessBeforeInstantiation method [Constructor] Call Person's constructor InstantiationAwareBeanPostProcessor calls postProcessPropertyValues method [Injecting attribute] Injecting attribute address [Injecting attribute] Injecting attribute name [Injecting attribute] Injecting attribute phone [BeanNameAware interface] Calling BeanNameAware.setBeanName() [BeanFactoryAware interface] Calling BeanFactoryAware.setBeanFactory() BeanPostProcessor interface method postProcessBeforeInitialization changes the attribute! [InitializingBean Interface] Call InitializingBean.afterPropertiesSet() [init-method] Call the initialization method specified by the init-method property of <bean>, BeanPostProcessor interface method postProcessAfterInitialization to change the property! InstantiationAwareBeanPostProcessor calls the postProcessAfterInitialization method. The container is initialized successfully. Person [address=Guangzhou, name=Zhang San, phone=110] Now start closing the container! 【DostibleBean interface】Call DiposibleBean.destory()【destroy-method】Call the initialization method specified by the destroy-method property of <bean>
The above is a compilation of the information on the life cycle of Java Spring Bean. We will continue to add relevant information in the future. Thank you for your support to this site!