Spring Framework Bean initialization and destruction — method: @Bean(initMethod = “init”, destroyMethod = “destroy”)

Initialization and destruction of Spring Framework Bean – method: @Bean(initMethod = “init”,destroyMethod = “destroy”)

Bean initialization

  • The initialization of beans in the Spring framework is divided into the following types

  • [External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture Save it and upload directly (img-xQbmPQV5-1690804568198)(C:\Users\quyanliang\AppData\Roaming\Typora\typora-user-images\1690804264910.png)]

  • Talking about beans must talk about life cycle

Bean life cycle

  • The name cycle of a bean in the usual sense refers to the process of a bean from creation to initialization, through a series of processes, and finally to destruction. However, in Spring, the bean life cycle is managed by the Spring container. In Spring, we can specify the bean initialization and destruction methods ourselves. When we specify bean initialization and pin

How to define initialization and destruction methods?

  • We already know that when Spring manages the life cycle of beans, we can specify the bean initialization and destruction methods, so how to define these initialization and destruction methods? Next, we introduce the first way to define initialization and destruction methods: Specify initialization and destruction methods through @Bean annotations.

  • If the bean is configured using an XML file, you can specify the bean initialization and destruction methods in the tag, as shown below.

  • <bean id = "person" class="io.mykit.spring.plugins.register.bean.Person" init-method="init" destroy-method="destroy">
        <property name="name" value="binghe"></property>
        <property name="age" value="18"></property>
    </bean>
    
  • Here, it should be noted that in the Person class we wrote, there needs to be an init() method and a destroy() method. Moreover, it is stipulated in Spring that the init() method and destroy() method here must be no-parameter methods, but exceptions can be thrown.

  • If we use annotations, how to implement the initialization and destruction methods of the specified bean? Next, let’s get it done together! !

  • First, create a class named Student, the implementation of this class is relatively simple, as shown below. When destroying the method, when the container reaches the stage of the current life cycle of the bean, it will automatically call our custom initialization and destruction methods.

  • package io.mykit.spring.plugins.register.bean;
     
    public class Student {
     
        public Student(){
            System.out.println("Student class constructor");
        }
     
        public void init(){
            System.out.println("Initialize the Student object");
        }
     
        public void destroy(){
            System.out.println("Destroy the Student object");
        }
    }
    
  • Next, we register the Student class object in the Spring container through annotations. The specific method is to create a new LifeCircleConfig class as the Spring configuration class, and register the Student class object in the Spring container through the LifeCircleConfig class. The code of the LifeCircleConfig class is as follows shown.

  • import io.mykit.spring.plugins.register.bean.Student;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
     
    @Configuration
    public class LifeCircleConfig {
        @Bean
        public Student student(){
            return new Student();
        }
    }
    
  • Next, we create a new BeanLifeCircleTest class to test the Student object in the container, part of the code of the BeanLifeCircleTest class is shown below.

  • public class BeanLifeCircleTest {
     
        @Test
     
        public void testBeanLifeCircle01(){
     
            //Create an IOC container
     
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LifeCircleConfig.class);
     
            System.out.println("Container created...");
     
        }
    }
    
  • For a single-instance bean object, the single-instance bean will be instantiated after the Spring container is created. Then, let’s run the testBeanLifeCircle01() method in the BeanLifeCircleTest class first, and the output result information is as follows.

  • (On the premise of not doing specialization, that is, the spring framework creates ordinary objects (beans), it will only build the current object construction method)

  • It can be seen that when the Spring container is created, the construction method of the single-instance bean is automatically called, and the single-instance bean is instantiated.

  • In short: for a single-instance bean, the object is created when the Spring container starts; for a multi-instance bean, the object is created every time the bean is obtained.

  • Now, we have specified the init() method and destroy() method in the Student class, so how to let the Spring container know that the init() method in the Student class is used to perform object initialization operations, and the destroy() method is used To perform the destruction operation of the object? If it is configured using an XML file, we can use the following configuration to achieve it.

  • <bean id="student" class="io.mykit.spring.plugins.register.bean.Student" init-method="init" destroy-method="destroy"> </bean>
    
  • How can we implement it in the @Bean annotation? In fact, it is even simpler. Let’s look at the source code of the @Bean annotation, as shown below.

  • import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
     
    import org.springframework.beans.factory.annotation.Autowire;
    import org.springframework.beans.factory.support.AbstractBeanDefinition;
    import org.springframework.core.annotation.AliasFor;
     
    @Target({ElementType. METHOD, ElementType. ANNOTATION_TYPE})
    @Retention(RetentionPolicy. RUNTIME)
    @Documented
    public @interface Bean {
     
        @AliasFor("name")
        String[] value() default {};
     
        @AliasFor("value")
        String[] name() default {};
     
        @Deprecated
        Autowire autowire() default Autowire.NO;
     
        boolean autowireCandidate() default true;
     
        String initMethod() default "";
     
        String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
    
    }
    
  • Seeing the source code of the @Bean annotation, I believe that the friends will have a sudden feeling of enlightenment: yes, it is to use the initMethod attribute and destroyMethod attribute of the @Bean annotation to specify the initialization method and destruction method of the bean.

  • Therefore, we specify the initMethod attribute and destroyMethod attribute in the @Bean annotation in the LifeCircleConfig class, as shown below.

  • @Bean(initMethod = "init", destroyMethod = "destroy")
    public Student student(){
        return new Student();
    }
    
  • At this point, let’s run the testBeanLifeCircle01() method in the BeanLifeCircleTest class again, and the output result information is as follows.

  • Construction method of the Student class
    Initialize the Student object
    Container created...
    
  • It can be seen from the output that in the Spring container, the constructor of the Student class is first called to create the Student object, and then the init() method of the Student object is called to initialize.

  • Then friends may ask, running the above code does not print out the information in the bean destruction method, so when will the bean destruction method be executed? This question is very good, the bean’s destruction method is called when the container is closed.

  • Next, we add the code to close the container in the testBeanLifeCircle01() method in the BeanLifeCircleTest class, as shown below. (context.close() This method represents the destruction of the container)

  • @Test
    public void testBeanLifeCircle01(){
        //Create an IOC container
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LifeCircleConfig.class);
        System.out.println("Container created...");
        context. close();
    }
    
  • Let’s run the testBeanLifeCircle01() method in the BeanLifeCircleTest class again, and the output result information is as follows.

  • Construction method of the Student class
    Initialize the Student object
    Container created...
    Destroy the Student object
    
  • It can be seen that the information in the object’s destruction method is output at this time, indicating that the object’s destruction method has been executed.

Specify usage scenarios of initialization and destruction methods

  • A typical usage scenario is the management of data sources. For example, when configuring a data source, when initializing, assign values to many data source attributes; when destroying, we need to close and clean up the connection and other information of the data source. At this point, we can do these things in our custom initialization and destruction methods!

When to initialize and destroy method calls

  • The timing of calling the initialization method of the bean object: After the object is created, if there are some properties in the object, and these properties are also assigned, the initialization method of the bean will be called. For a single-instance bean, after the Spring container is created, the Spring container will automatically call the bean initialization and destruction methods; for a multi-instance bean, the bean initialization and destruction methods will be called each time the bean object is obtained.

  • Timing of bean object destruction method call: For single-instance beans, when the container is closed, the bean destruction method will be called; for multi-instance beans, the Spring container will not manage this bean, nor will it automatically call this The destroy method of the bean. However, friends can manually call the destruction method of multi-instance beans.

  • Earlier, we have already talked about the initialization and destruction methods of single instance beans. Next, let’s talk about the initialization and destruction methods of multi-instance beans. We turn the Student object into a multi-instance bean to verify. Next, we set the Student object as a multi-instance bean through the @Scope annotation on the student() method of the LifeCircleConfig class, as shown below.

  • @Scope("prototype")
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Student student(){
        return new Student();
    }
    
  • Next, let’s run the testBeanLifeCircle01() method in the BeanLifeCircleTest class, and the output information is as follows.

  • Container created...
    
  • It can be seen that when we set the Student object as a multi-instance bean and do not get the bean instance object, the Spring container does not execute the bean’s construction method, initialization method and destruction method.

  • Speaking of this, we add a line of code to obtain the Student object in the testBeanLifeCircle01() method in the BeanLifeCircleTest class, as shown below.

  • @Test
    public void testBeanLifeCircle01(){
        //Create an IOC container
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LifeCircleConfig.class);
        System.out.println("Container created...");
        context. getBean(Student. class);
        context. close();
    }
    
  • At this point, let’s run the testBeanLifeCircle01() method in the BeanLifeCircleTest class again, and the output result information is as follows.

  • Container created...
    The constructor of the Student class
    Initialize the Student object
    
  • It can be seen that at this time, the information in the construction method and initialization method is output in the result information. But when the container is closed, the information in the bean’s destruction method is not output.

  • This is because Spring does not automatically call the bean object’s destruction method when the bean is set to multiple instances. As for when the multi-instance bean object is destroyed, that is the programmer’s own business! ! The Spring container no longer manages multi-instance beans.