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的使用
在以下场景中会用到:
-
bean赋值 注入其他组件
-
@Autowired
-
生命周期注解功能
-
@Async 异步功能
…