The life cycle of the Bean
It can be divided into four stages: instantiation → attribute assignment → initialization → destruction. Some classes and interfaces provided by Spring can control the behavior of beans in each stage
The preparatory work
Entity class
public class User {
private int uid;
private String name;
// Getter, setter, toString
}
Copy the code
Spring configuration file
<bean id="user" class="domain.User">
<property name="uid" value="1"/>
<property name="name" value="Zhang"/>
</bean>
Copy the code
InstantiationAwareBeanPostProcessorAdapter
InstantiationAwareBeanPostProcessorAdapter provides operating bean at some time in the life cycle of method, we only need to inherit it and rewrite the method, the need to take this class registered in the spring container This class is a container level, All the methods in this class applies to all the beans in the container if there are no special instructions below mentioned method, the default in InstantiationAwareBeanPostProcessorAdapter method
instantiation
<bean id="user" class="domain.User">
<property name="uid" value="10"/>
<property name="name" value="Zhang"/>
</bean>
<! - registered InstantiationAwareBeanPostProcessorAdapter class -- >
<bean class="MyInstantiationAwareBeanPostProcessor"/>
Copy the code
Inheritance InstantiationAwareBeanPostProcessorAdapter, rewrite postProcessBeforeInstantiation method, this method in the bean is instantiated before execution
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException {
if ("user".equals(beanName)) {
System.out.println(beanName + "Before instantiation ------------------");
}
return null; }}Copy the code
Test the
AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Copy the code
Output result:
PostProcessBeforeInstantiation method after the execution, next, spring will according to instantiate bean constructors.
If postProcessBeforeInstantiation method, return to a bean instance, the spring would not be instantiated bean, because you have been good to instantiate a bean, and as a method return values, Instead of simply returning a new bean object that is not managed by the Spring container, you need to use the method provided by Spring to create the new object. If we legitimate object of returned to the bean, the next will perform the postProcessAfterInitialization InstantiationAwareBeanPostProcessorAdapter method, this method is the initialization phase correlation method
After spring according to the constructor instantiates a bean, the next will be executed postProcessAfterInstantiation method, this method after instantiate execution, rewrite the method
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "Before instantiation ------------------");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "After instantiation ------------------");
}
return true; }}Copy the code
Found in postProcessAfterInstantiation method on breakpoints, there is no attribute assignment of bean
Output result:
Attribute assignment
Instantiation phase has been completed, the next stage in attribute assignment postProcessProperties method, the method is performed before attribute assignment, the method depends upon whether perform postProcessAfterInstantiation methods return values. True: execute false: not execute
Rewrite the postProcessProperties method and change the name property to Li Si.
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "Before instantiation ------------------");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "After instantiation ------------------");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("user".equals(beanName)) {
System.out.println(beanName + "Before attribute assignment ------------------");
PropertyValue pv = pvs.getPropertyValue("name");
pv.setConvertedValue("Bill");
return pvs;
}
return null; }}Copy the code
If the property in the bean is not explicitly configured in the Spring configuration file, the PVS will not record the property, and pv=null will cause a null pointer exception
<bean id="user" class="domain.User">
<property name="uid" value="10"/> <! PVS will not record the uid attribute if this attribute is not explicitly configured.
<property name="name" value="Zhang"/> <! -- Display configuration -->
</bean>
Copy the code
Put a breakpoint on postProcessProperties
The output
After executing the postProcessProperties method, Spring assigns properties to the bean
Initialize the
Next, enter the initialization phase, rewrite postProcessBeforeInitialization method, this method in the bean’s initialization before the execution
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "Before instantiation ------------------");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "After instantiation ------------------");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("user".equals(beanName)) {
System.out.println(beanName + "Before attribute assignment ------------------");
PropertyValue pv = pvs.getPropertyValue("name");
pv.setConvertedValue("Bill");
return pvs;
}
return null;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "Pre-initialization");
}
returnbean; }}Copy the code
Output result:
If the bean implements the InitializingBean interface, the afterPropertiesSet method in the interface will be executed
public class User implements InitializingBean {
private int uid;
private String name;
@Override
public void afterPropertiesSet(a) throws Exception {
System.out.println("AfterPropertiesSet method in InitializingBean executed");
}
// setter, getter, toString
}
Copy the code
Output result:
Next, if the init-method property is configured in the bean label, init-method will be executed
<bean id="user" class="domain.User" init-method="initMethod">
<property name="uid" value="1"/>
<property name="name" value="Zhang"/>
</bean>
Copy the code
public class User implements InitializingBean {
private int uid;
private String name;
@Override
public void afterPropertiesSet(a) throws Exception {
System.out.println("AfterPropertiesSet method in InitializingBean executed");
}
public void initMethod(a) {
System.out.println("Init-method in bean tag");
}
// setter, getter, toString
}
Copy the code
Output result:
Next spring initialized to bean, spring also provides control bean after initialization method of behavior postProcessAfterInitialization, rewrite the method
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "Before instantiation ------------------");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "After instantiation ------------------");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("user".equals(beanName)) {
System.out.println(beanName + "Before attribute assignment ------------------");
PropertyValue pv = pvs.getPropertyValue("name");
pv.setConvertedValue("Bill");
return pvs;
}
return null;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "Pre-initialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("user".equals(beanName) {
System.out.println(beanName + "After initialization");
}
returnbean; }}Copy the code
Output result:
Mentioned earlier, if postProcessBeforeInstantiation returned to a legitimate bean, then direct execution postProecessAfterInitialization method
How to return a valid beans, here only to the User, we modify postProcessBeforeInstatiation method
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException {
if ("user".equals(beanName)) {
System.out.println(beanName + "Before instantiation ------------------");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanClass);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("Before objective method :" + method+"\n");
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("After target method :" + method+"\n");
returnobject; }});return (User) enhancer.create();
}
return null; }}Copy the code
Output result:
If you specify scope=”prototype” in the bean tag, return the bean to the caller, who is responsible for managing the bean’s life cycle. Spring no longer manages the life cycle of this Bean. If the scope is set to scope=”singleton”, the Bean is put into the cache pool of the Spring IoC container and the application of the Bean is returned to the caller, and Spring continues to manage the beans for subsequent life
The destruction
For beans whose Scope = “Singleton”, when the container closes, Spring will be triggered to manage the subsequent lifecycle of the Bean. If the Bean implements the DisposableBean interface, The interface’s destroy() method is called. For a Bean with scope= “Singleton,” Spring will execute the Bean’s destruction method if the Bean’s destruction method is specified through the destory-method attribute of the Bean tag
public class User implements InitializingBean.DisposableBean {
private int uid;
private String name;
@Override
public void afterPropertiesSet(a) throws Exception {
System.out.println("AfterPropertiesSet method in InitializingBean executed");
}
@Override
public void destory(a) throws Exception {
System.out.println("Destory method executes in DisposableBean.");
}
public void initMethod(a) {
System.out.println("Init-method in bean tag");
}
public void destoryMethod(a) {
System.out.println("DestoryMethod in bean tag");
}
// setter, getter, toString
}
Copy the code
<bean id="user" class="domain.User" init-method="initMethod" destory-method="destoryMethod">
<property name="uid" value="1"/>
<property name="name" value="Zhang"/>
</bean>
Copy the code
Closing the Spring container
AbstractApplicationContext context = new ClassPathXmlApplicationContext("config\spring.xml");
context.registerShutdownHook();
Copy the code
Output result:
conclusion
InitializingBean and DisposableBean are bean-level interfaces, which have the same effect as init-method and Destory-method, but spring has hacked our code for the former, It is recommended to use the latter InstantiationAwareBeanPostProcessorAdapter container level is class, it can control the bean is instantiated before, instantiated, initialize the behavior before and after initialization