Spring annotation-driven development [02-life cycle]

Spring annotation-driven development [life cycle]

1. @Bean specifies initialization and destruction methods

bean life cycle

bean的生命周期:
    创建 -> 初始化 -> 销毁

After the spring is injected, the container manages the life cycle of the bean:
we can customize the initialization and destruction methods. The container calls our custom initialization and destruction methods when the bean reaches the current life cycle.

1.1.init-Method与destroyMethod

Add init-method="" destroy-method="" when defining beans in the xml configuration file

or

Defined by @Bean(initMethod="",destroyMethod="")

  • Define an entity class Car
public class Car {
    
    
    public Car() {
    
    
        System.out.println("Car constructor...");
    }
//	定义初始化方法
    public void init(){
    
    
        System.out.println("Car init...");
    }
//	定义销毁方法
    public void destroy(){
    
    
        System.out.println("Car destroy...");
    }
}
  • Define a configuration class
@Configuration
public class ConfigOfLifeCycle {
    
    
        @Bean(initMethod = "init" , destroyMethod = "destroy")
        public Car car(){
    
    
            return new Car();
        }
}
  • Test by test class
public class MyTest02 {
    
    
    @Test
    public void test(){
    
    
//        创建ioc容器 (单例bean会在创建容器的同时就被实例化,同时进行初始化)
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
        System.out.println("容器创建完成....");
//        关闭ioc容器会将所有单例bean一同销毁
        context.close();
        System.out.println("容器销毁结束...");
    }
}

operation result:

Car constructor...	
Car init...
容器创建完成....
Car destroy...
容器销毁结束...
  • Scope the injected Car
@Scope("prototype")
@Bean(initMethod = "init" , destroyMethod = "destroy")
  • Test again
容器创建完成....
容器销毁结束...

to sum up:

bean的生命周期:
    创建 -> 初始化 -> 销毁
        创建:单例bean会在创建容器的同时就被实例化
             多实例bean会在每次获取的时候创建对象
        初始化:对象创建完成并赋值好后 调用初始化方法 多实例bean会在调用bean时进行初始化
              通常情况下 可以在初始化时为容器配置一些数据源或初始化数据等
        销毁:单例bean容器关闭时进行销毁 多实例bean的销毁不会被spring容器接管
              通常情况下 可以在销毁时做一些收尾工作 例如关闭一些连接等

1.2. Customize initialization and destruction by letting entity classes implement InitializingBean and DisposableBean

  • Customize an entity class and implement the InitializingBean (initialization) and DisposableBean (destroy) interfaces provided by spring
@Component	//要实现ComponentScan进行组件扫描 
public class Cat implements DisposableBean, InitializingBean {
    
    
    public Cat() {
    
    
        System.out.println("Cat constructor...");
    }

    public void afterPropertiesSet() throws Exception {
    
    
        System.out.println("Cat afterPropertiesSet....");
    }

    public void destroy() throws Exception {
    
    
        System.out.println("Cat destory...");
    }

}

  • Add scan component annotation to configuration class

    @ComponentScan(value = "indi.zhihuali.pojo")
    public class ConfigOfLifeCycle {
          
          
        ...
    }
    
  • test

    @Test
    public void test(){
    
    
//        创建ioc容器 (单例bean会在创建容器的同时就被实例化)
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
        System.out.println("容器创建完成....");
//        关闭ioc容器会将所有单例bean一同销毁
        context.close();
        System.out.println("容器销毁结束...");
    }
}

operation result:

Cat constructor...
Cat afterPropertiesSet....
Car constructor...
Car init...
容器创建完成....
Car destroy...
Cat destory...
容器销毁结束...

It can be seen that custom initialization and destruction configuration can also be performed

1.3. By using Spring-defined JSR250 annotations

@PostConstruct:在bean创建完成并属性赋值完成时 执行初始化方法
@PreDestroy:在容器销毁bean前通知我们完成清理工作
  • Custom pojo entity class and register ioc bean

    @Component
    public class Dog {
          
          
        public Dog() {
          
          
            System.out.println("dog constructor...");
        }
        
    //    对象创建并赋值后调用
        @PostConstruct
        public void init(){
          
          
            System.out.println("dog @PostConstruct....init....");
        }
        
    //    对象移除之前
        @PreDestroy
        public void destroy(){
          
          
            System.out.println("dog @PreDestroy...destroy...");
        }
    }
    
  • test

@Test
    public void test(){
    
    
//        创建ioc容器 (单例bean会在创建容器的同时就被实例化)
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
        System.out.println("容器创建完成....");
//        关闭ioc容器会将所有单例bean一同销毁
        context.close();
        System.out.println("容器销毁结束...");
    }

Output:

dog constructor....
dog @PostConstruct....init....
容器创建完成....
dog @PreDestroy...destroy...
容器销毁结束...

2. BeanPostProcessor post processor

2.1. Use of BeanPostProcessor interface

BeanPostProcessor【interface】:bean的后置处理器
  postProcessBeforeInitialization:初始化前调用
  postProcessAfterInitialization: 初始化后调用

Customize a class that implements the BeanPostProcessor interface and register the bean

@Component
//      后置处理器:初始化前后进行工作
public class MyBeanPostProcessor implements BeanPostProcessor {
    
    
//   	bean初始化前工作
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("postProcessBeforeInitialization..."+bean+" name:"+beanName);
        return bean;
    }

//   	bean初始化后工作
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("postProcessAfterInitialization..."+bean+" name:"+beanName);
        return bean;
    }
}

  • test
@Test
    public void test(){
    
    
//        创建ioc容器 (单例bean会在创建容器的同时就被实例化)
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
        System.out.println("容器创建完成....");
//        关闭ioc容器会将所有单例bean一同销毁
        context.close();
        System.out.println("容器销毁结束...");
    }

The result is:

<!--spring内部组件初始化前后也同样调用了这两个方法-->
postProcessBeforeInitialization...indi.zhihuali.config.ConfigOfLifeCycle$$EnhancerBySpringCGLIB$$4dd9ed7c@1d016c9 name:configOfLifeCycle
postProcessAfterInitialization...indi.zhihuali.config.ConfigOfLifeCycle$$EnhancerBySpringCGLIB$$4dd9ed7c@1d016c9 name:configOfLifeCycle

<!--自定义bean实现该两种方法-->
<!-- Cat创建 -->
Cat constructor...
<!-- Cat初始化前 -->
postProcessBeforeInitialization...indi.zhihuali.pojo.Cat@167e60c name:cat
<!-- 通过1.2中的方法对Cat进行初始化 -->
Cat afterPropertiesSet....
<!-- Cat初始化结束 -->
postProcessAfterInitialization...indi.zhihuali.pojo.Cat@167e60c name:cat
<!-- Dog创建 -->
dog constructor...
<!-- Dog初始化前 -->
postProcessBeforeInitialization...indi.zhihuali.pojo.Dog@ee5251 name:dog
<!-- 通过1.3中的方法对Dog进行初始化 -->
dog @PostConstruct....init....
<!-- Dog初始化结束 -->
postProcessAfterInitialization...indi.zhihuali.pojo.Dog@ee5251 name:dog
Car constructor...
postProcessBeforeInitialization...indi.zhihuali.pojo.Car@23e5ee name:car
Car init...
postProcessAfterInitialization...indi.zhihuali.pojo.Car@23e5ee name:car
容器创建完成....
Car destroy...
dog @PreDestroy...destroy...
Cat destory...
容器销毁结束...

Therefore, the life cycle of the bean after adding BeanPostProcessor can be divided into:

bean的生命周期:
    创建 -> 初始化 -> 销毁
        创建:单例bean会在创建容器的同时就被实例化
             多实例bean会在每次获取的时候创建对象
        BeanPostProcessor.postProcessBeforeInitialization:初始化前调用   
        初始化:对象创建完成并赋值好后 调用初始化方法 多实例bean会在调用bean时进行初始化
              通常情况下 可以在初始化时为容器配置一些数据源或初始化数据等
        BeanPostProcessor.postProcessAfterInitialization: 初始化后调用  
        销毁:单例bean容器关闭时进行销毁 多实例bean的销毁不会被spring容器接管
              通常情况下 可以在销毁时做一些收尾工作 例如关闭一些连接等

2.2. Principle of BeanPostProcessor interface

Debug postProcessBeforeInitialization and postProcessAfterInitialization in custom BeanPostProcessor

Insert picture description here

原理:(debug)
           遍历得到容器中所有的BeanPostProcessor 并逐个执行beforeInitialization
           一旦方法返回null,跳出for循环
           并且不会执行后边的 BeanPostProcessor 的 applyBeanPostProcessorsBeforeInitialization方法

       先执行:
           populateBean(beanName, mbd, instanceWrapper);   给bean属性赋值
       其次:
           initBean{
                applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
                invokeInitMethods(beanName, wrappedBean, mbd);	执行初始化
                applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
    

2.3. The use of BeanPostProcessor at the bottom of Spring

It will be used in the following scenarios:

  1. Bean assignment injects other components

  2. @Autowired

  3. Life cycle annotation function

  4. @Async asynchronous function

Guess you like

Origin blog.csdn.net/weixin_45729934/article/details/108685155