spring Source Read Notes 10: bean Life Cycle

The previous articles focused on analyzing SpringThe principle of the IOC Container section, the core logic of which is related to the creation and management of beans. For the management of single beans, from creation to caching to destruction, there is a complete life cycle, and Spring also provides multiple interfaces for users to extend themselves throughout the creation of beans. This article combs the life cycle of beans in Spring.

1. Life cycle of beans in Spring containers

For a prototype scoped Bean, the Spring container is only responsible for creating it. When the container creates a Bean instance, the Bean instance is completely handed over to client code management and the container no longer tracks its life cycle.Each time a client requests a prototype-scoped Bean, Spring generates a new instance. The Spring container does not know how many prototype-scoped Beans it has created or when these prototype-scoped Beans will be destroyed.Therefore, Spring cannot manage beans for the prototype scope.

_For singleton scoped beans, the same shared instance is returned every time a client code requests it. Client code cannot control the destruction of beans. The Spring container is responsible for tracking the generation and destruction of bean instances.The Spring container can make requests for some generic resources after the Bean is created; it can also recycle some resources, such as database connections, before destroying the Bean instance.

_Take a look at the full life cycle of Spring Bean, starting with the creation of the Spring container and ending with the destruction of the Bean by the Spring container:

The life cycle levels of beans in the Spring container are divided into four levels:

  • Bean's own method;
  • Bean-level life cycle interface method;
  • Container-level life cycle interface method;
  • Factory post processor interface method.

1.1 Bean's own method

_Bean's own methods: call the constructor to instantiate the bean, call setter to set properties, call init-method, destroy-method.

1.2 Bean Level Life Cycle Interface Method

_Bean-level life cycle methods, such as BeanNameAware, BeanFactoryAware, InitializingBean, and Disposable Bean, are implemented directly by beans.

1.3 Container Level Life Cycle Interface Method

_Container-level life cycle interface methods: There are two interface implementations, InstantiationAwareBeanPostProcessor and BeanPostProcessor, whose implementation class is generally referred to as post-processor.The implementation class is bean independent and is registered with spring as a container attachment.These post-processors work when spring creates any beans, so the impact of the post-processor is global.Of course, users can write postprocessors reasonably so that they can only process beans of interest.

_Bean level life interface and container level life interface are the reflection of the dialectical unity of individuality and commonality.The former solves the problem of personalized processing of beans, while the latter solves the problem of common processing of some beans in containers.

1.4 Process Processor Interface Method

_Factory-level life cycle interface methods (implementation classes of the BeanFactoryPostProcessor interface) handle the definition of beans (configuration metadata).That is, the Spring IoC container allows BeanFactoryPostProcessor to read configuration metadata before the container actually instantiates any other beans and possibly modify it.

2. bean Life Cycle Demo Example

_Following is an example of how to actually experience the invocation of each key interface method in the life cycle of a bean.The FruitStore class defines Bean's own methods and Bean-level life cycle methods:

public class FruitStore implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean{

    private String name;  
    private String address;  
    
    private ApplicationContext applicationContext;  
    private String             beanName;  
  
    public FruitStore() {  
        System.out.println("[FruitStore]--constructor");  
    }
    
    /** Bean Self-method**/  
    
    // adopt<bean>Of init-method Initialization method specified by property  
    public void myInit() {  
        System.out.println("[Bean Self-approach] [init-method]  Initialization Method...");  
    }  
      
    // adopt<bean>Of destroy-method Initialization method specified by property  
    public void myDestory() {  
        System.out.println("[Bean Self-approach] [destroy-method]  destroy-method...");  
    }  
      
    public void sayHello() {  
        System.out.println("[Bean Self-approach]  sayHello...");  
    }
    
    /** Bean Level Life Interface Method begin **/  
    
    public void setName(String name) {  
        this.name = name;  
        System.out.println("[Bean Level interface] [Injection Properties]  Injection Properties name...");  
    }  
  
    public void setAddress(String address) {  
        this.address = address;  
        System.out.println("[Bean Level interface] [Injection Properties]  Injection Properties address...");  
    }
    
    
    // DiposibleBean Interface Method
    public void destroy() throws Exception {
        System.out.println("[Bean Level interface]  destroy-method...");
    }

    // InitializingBean Interface Method
    public void afterPropertiesSet() throws Exception {
        System.out.println("[Bean Level interface] [InitializingBean Interface]  Initialization Method...");
    }

    // BeanFactoryAware Interface Method
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        this.applicationContext = arg0;  
        System.out.println("[Bean Level interface] [ApplicationContextAware Interface]  injection Spring container ApplicationContext..."); 
    }

    // BeanNameAware Interface Method
    public void setBeanName(String name) {
        this.beanName = name;  
        System.out.println("[Bean Level interface] [BeanNameAware Interface]  injection beanName...");
    }
    
    @Override  
    public String toString() {  
        return "FruitStore [name=" + name + 
                ", address=" + address + 
                ", applicationContext=" + applicationContext + 
                ", beanName=" + beanName + 
                "]";  
    } 
}

Implement two container-level interfaces, first the InstantiationAwareBeanPostProcessor interface:

public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
    
    public MyInstantiationAwareBeanPostProcessor() {  
        super();  
        System.out.println("[Container level interface] [InstantiationAwareBeanPostProcessor Implementation Class]--constructor");  
    }  
  
    // instantiation Bean Previous call  
    @Override  
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {  
        System.out.println("[Container level interface] [InstantiationAwareBeanPostProcessor Implementation Class]--instantiation Bean Previous call");  
        return null;  
    }  
  
    // instantiation Bean Called after  
    @Override  
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {  
        System.out.println("[Container level interface] [InstantiationAwareBeanPostProcessor Implementation Class]--instantiation Bean Called after");  
        return true;  
    }  
  
    // Initialization Bean Previous call  
    @Override  
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
        System.out.println("[Container level interface] [InstantiationAwareBeanPostProcessor Implementation Class]--Initialization Bean Previous call");  
        return bean;  
    }  
  
    // Initialization Bean Called after  
    @Override  
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
        System.out.println("[Container level interface] [InstantiationAwareBeanPostProcessor Implementation Class]--Initialization Bean Called after");  
        return bean;  
    }  
  
    // Called when a property is set  
    @Override  
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,  
            String beanName) throws BeansException {  
        System.out.println("[Container level interface] [InstantiationAwareBeanPostProcessor Implementation Class]--instantiation Bean Then, when a property is set, it is called");  
        return pvs;  
    }  
}

Then implement the BeanPostProcessor interface:

public class MyBeanPostProcessor implements BeanPostProcessor{

    public MyBeanPostProcessor() {  
        System.out.println("[Container level interface] [MyBeanPostProcessor Implementation Class]--constructor");  
    }  
  
    // Initialization Bean Previous call  
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
        System.out.println("[Container level interface] [BeanPostProcessor Implementation Class]--Initialization Bean Previous call");  
        return bean;  
    }  
  
    // Initialization Bean Called after  
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
        System.out.println("[Container level interface] [BeanPostProcessor Implementation Class]--Initialization Bean Called after");  
        return bean;  
    }  
}

Factory-level life cycle interface method (implementation class of BeanFactoryPostProcessor interface):

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{

    public MyBeanFactoryPostProcessor() {  
        super();  
        System.out.println("[Factory level interface] [BeanFactoryPostProcessor Implementation Class]--constructor");  
    }  
    
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {  
        System.out.println("[Factory level interface] [BeanFactoryPostProcessor Implementation Class] Spring After the container is loaded, all Bean Called before instantiation");  
        // Rewrite Person Bean Of phone attribute  
        BeanDefinition bd = arg0.getBeanDefinition("fruitStore");  
        bd.getPropertyValues().addPropertyValue("name", "papaya-mangos");  
    }  
}

Configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
        <!-- Define a factory-level life cycle interface. -->  
    <bean id="beanFactoryPostProcessor" class="spring.source.MyBeanFactoryPostProcessor"></bean>  
  
    <!-- Define a container-level life cycle interface. -->  
    <bean id="beanPostProcessor" class="xxx.xxx"></bean>  
    <bean id="instantiationAwareBeanPostProcessor" class="xxx.xxx"></bean>  
      
    <!-- Definition Bean Self and Bean Level life cycle interface. -->  
    <bean id="fruitStore" class="xxx.xxx"   
            init-method="myInit"   
            destroy-method="myDestory"   
            scope="singleton">  
        <property name="name"    value="Yonghui Supermarket"></property>  
        <property name="address" value="Hangzhou"></property>   
    </bean>  
</beans>

- Test code:

public static void main(String[] args) {
        try{
            System.out.println("============================== Start initializing the container now. ==============================");
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");    
       System.out.println("\r\n============================== Container initialization succeeded. =============================="); //obtain Preson,And use FruitStore fruitStore = ctx.getBean("fruitStore",FruitStore.class); fruitStore.sayHello(); System.out.println(fruitStore); System.out.println("\r\n============================== Start closing the container now! =============================="); ctx.close(); }catch (Exception e){ e.printStackTrace(); } }

The results are:

The above run results are analyzed here:

  1. Prepare Spring Container

    • Instantiate BeanFactoryPostProcessor implementation class;
    • Execute BeanFactoryPostProcessor's postProcessBeanFactory to modify XML meta-information for Bean configuration, here is to change the name attribute value of fruitStore this Bean;
  2. Instantiate Bean

    • Instantiate BeanPostProcessor implementation class;
    • InstantiationAwareBeanPostProcessorAdapter implementation class is instantiated;
    • Call the postProcessBeforeInstantiation method of InstantiationAwareBeanPostProcessor before Bean instantiates;
    • Call FruitStore's constructor for instantiation;
    • The InstantiationAwareBeanPostProcessor postProcessAfterInstantiation method is called after the Bean is instantiated;
    • Before property injection, you can modify the Bean's property information by calling the postProcessPropertyValues method of InstantiationAwareBeanPostProcessor;
  3. Injection Dependency

    • Injection properties: name, address;
  4. Initialize Bean

    • Inject BeanName;
    • Inject the ApplicationContext;
    • Call BeanPostProcessor implementation class call interface method postProcessBeforeInitialization before initializing Bean;
    • Call the postProcessBeforeInitialization method of InstantiationAwareBeanPostProcessor before initializing the Bean;
    • Initializing Bean is called to implement the afterPropertiesSet() of the class for initialization of beans;
    • Call the initialization method specified by the init-method property of <bean>
    • Initialize Bean and call BeanPostProcessor to implement the class interface method postProcessAfterInitialization;
    • Call the postProcessAfterInitialization method of InstantiationAwareBeanPostProcessor after initializing the Bean;
  5. Use Bean

    • Call the sayHello() method;
    • Print FruitStore information (you can see that the name has been changed to papaya-mangos, which is different from the configuration file);
  6. Destroy Bean

    • Call the destory method of the DiposibleBean interface;
    • Call the destroy method specified by the destroy-method property of <bean>

3. Summary

_This paper summarizes the life cycle of Bean in Spring, including the following processes:

  • Spring container preparation, where the implementation class of factory-level postprocessor BeanFactoryPostProcessor can be applied;
  • Instantiate Bean, where you can apply the container-level post-processing InstantiationAwareBeanPostProcessor implementation class to do some work before and after instantiating the Bean;
  • Dependent on injection, here you can apply the implementation class of container-level postprocessor InstantiationAwareBeanPostProcessor to do some processing before property injection.
  • Beans are initialized, where Bean-level life cycle interface methods (BeanNameAware, InitializingBean, and so on) and container-level postprocessor BeanPostProcessor implementation classes can be applied;
  • Use Bean;
  • Destroy Bean, where the Bean-level life cycle interface method DisposableBean and the Bean's own method destroy-method are applied;

_Summarizes three main ways to configure the life cycle of a Bean:

  • Inherit interfaces, such as BeanNameAware, InitializingBean, and so on;
  • Configure xml configuration files, such as init-method, destroy-method;
  • Add processors, such as implementing BeanPostProcessor;

_Destroy and initialize beans by configuring the init-method and destroy-method attributes of <beans>. The effect of this method is exactly the same as that of the Disposable bean interface by implementing InitializingBean. However, the former configuration can make beans not bind to a specific spring interface, the former is "not applied" to springThe theory that program classes make any restrictions is consistent.

Unlike post-processor interfaces such as BeanPostProcessor, which do not require beans to inherit it, they are registered in the spring container exactly like plug-ins, providing additional functionality to the container.Spring makes full use of BeanPostProcessor to process beans (SpringAOP is based on this, which will be discussed later).

The core function of spring as an ioc container is to manage the creation of beans and the dependencies between beans. Further, spring manages the entire life cycle of beans, from instantiation to initialization, to cached beans and to destroy beans.Spring provides a variety of ways (as described above) to make it easy for users to do custom actions throughout the life cycle of a bean.This is also an excellent design methodology reflected in spring, easy to change, open to extension.

Tags: Spring xml Attribute Database

Posted on Wed, 06 May 2020 18:04:27 -0700 by justgrafx