Spring 注解驱动开发【02-生命周期】

Spring 注解驱动开发【生命周期】

1. @Bean指定初始化和销毁方法

bean的生命周期

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

注入spring后 由容器对bean的生命周期进行管理:
我们可以自定义初始化和销毁方法 容器在bean进行到当前生命周期时调用我们自定义的初始化和销毁方法

1.1.init-Method与destroyMethod

在xml配置文件中定义bean时追加 init-method="" destroy-method=""

或者

通过@Bean(initMethod="",destroyMethod="")进行定义

  • 定义一个实体类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...");
    }
}
  • 定义一个配置类
@Configuration
public class ConfigOfLifeCycle {
    
    
        @Bean(initMethod = "init" , destroyMethod = "destroy")
        public Car car(){
    
    
            return new Car();
        }
}
  • 通过测试类进行测试
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("容器销毁结束...");
    }
}

运行结果:

Car constructor...	
Car init...
容器创建完成....
Car destroy...
容器销毁结束...
  • 给注入的Car进行作用域规定
@Scope("prototype")
@Bean(initMethod = "init" , destroyMethod = "destroy")
  • 再次进行测试
容器创建完成....
容器销毁结束...

总结:

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

1.2.通过让实体类implements InitializingBean,DisposableBean 进行自定义初始化及销毁

  • 自定义一个实体类并实现spring提供的 InitializingBean(初始化) 和 DisposableBean(销毁)接口
@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...");
    }

}

  • 给配置类添加扫描组件注解

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

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

运行结果:

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

可见同样可以进行自定义初始化及销毁配置

1.3.通过使用Spring定义的JSR250注解

@PostConstruct:在bean创建完成并属性赋值完成时 执行初始化方法
@PreDestroy:在容器销毁bean前通知我们完成清理工作
  • 自定义pojo实体类并注册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
    public void test(){
    
    
//        创建ioc容器 (单例bean会在创建容器的同时就被实例化)
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
        System.out.println("容器创建完成....");
//        关闭ioc容器会将所有单例bean一同销毁
        context.close();
        System.out.println("容器销毁结束...");
    }

输出:

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

2. BeanPostProcessor 后置处理器

2.1.BeanPostProcessor接口的使用

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

自定义一个实现了BeanPostProcessor接口的类并注册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
    public void test(){
    
    
//        创建ioc容器 (单例bean会在创建容器的同时就被实例化)
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
        System.out.println("容器创建完成....");
//        关闭ioc容器会将所有单例bean一同销毁
        context.close();
        System.out.println("容器销毁结束...");
    }

结果为:

<!--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...
容器销毁结束...

因此添加了BeanPostProcessor后 bean的生命周期可划分为:

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

2.2.BeanPostProcessor接口的原理

对自定义BeanPostProcessor中的postProcessBeforeInitialization和postProcessAfterInitialization进行debug

在这里插入图片描述

原理:(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.Spring底层对BeanPostProcessor的使用

在以下场景中会用到:

  1. bean赋值 注入其他组件

  2. @Autowired

  3. 生命周期注解功能

  4. @Async 异步功能

猜你喜欢

转载自blog.csdn.net/weixin_45729934/article/details/108685155