Spring 中控制 Bean 生命周期的几种方式及 BeanPostProcessor 执行原理
一、几种方式总览
- @Bean 注解的方式;
- 通过实现接口的方式;
- 使用
JSR250
提供的两个注解; -
BeanPostProcessor
后置处理器;
二、@Bean 的方式
可以使用 @Bean
注解的两个属性设置初始化和销毁方法:
@Bean(initMethod = "init", destroyMethod = "destroy")
public Car car() {
return new Car();
}
这里在实体类中创建了几个方法。
public class Car {
public Car() {
System.out.println("汽车构造器...");
}
public void init() {
System.out.println("汽车初始化...");
}
public void destroy() {
System.out.println("汽车销毁了...");
}
}
实际的测试结果如下:
汽车构造器...
汽车初始化了...
容器初始化了...
三、InitializingBean 和 DisposableBean 的方式
这两个类都是接口,其中 InitializingBean
有一个抽象方法 afterPropertiesSet
,DisposableBean
有一个抽象方法 destroy
,分别代表 init
和 destroy
方法。
继承之后可以重写这两个方法:
public void destroy() {
System.out.println("汽车销毁了...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("汽车初始化了...");
}
效果也和上面一样,这样就不用再使用 @Bean 指定初始化和销毁方法了。
注意:
- 这里的对象均为单例的对象,所以在容器初始化的时候就加载了;
- 注意如果是多例的对象要加以区分。
四、@PostConstruct 和 @PreDestroy 注解
这两个注解都是 JSR250
提供的注解:
-
@PostConstruct
: 在 bean 创建完成并且属性赋完值的时候调用方法; -
@PreDestroy
: 在容器销毁 bean 之前通知我们进行清理操作;
该注解在实体类上的方法使用:
/**
* 对象创建并赋值之后调用
*/
@PostConstruct
public void init() {
System.out.println("汽车初始化...");
}
/**
* 容器移除对象之前调用
*/
@PreDestroy
public void destroy() {
System.out.println("汽车销毁了...");
}
五、BeanPostProcessor 后置处理器
该类的作用就是在 bean
初始化前后进行一些处理工作,它是一个接口;
该接口有两个方法:
-
postProcessBeforeInitialization
:在初始化之前调用; -
postProcessAfterInitialization
: 在初始化之后调用;
所以我们可以写一个实现类来实现这些方法:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之前:" + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之后:" + beanName);
return bean;
}
}
执行之后,这两个方法会在初始化方法被调用的前后分别被调用,应用于容器中所有的 bean
。
六、BeanPostProcessor 的执行原理
下面分析一下 BeanPostProcessor 的执行原理:
这是截取的一段源代码,出自 AbstractAutowireCapableBeanFactory
类,该方法叫做 doCreateBean
:
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
这段代码很容易理解,就是初始化 bean 实例,涉及两个方法:
-
populateBean
:将属性值填充到Bean
中,就是给 Bean 属性赋值; -
initializeBean
:初始化Bean
;
来看一下该类的 initializeBean
方法做了什么:
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
该方法中有三处比较重要:
-
applyBeanPostProcessorsBeforeInitialization
:在 Bean 初始化之前执行; -
invokeInitMethods
:执行自定义初始化; -
applyBeanPostProcessorsAfterInitialization
:在 Bean 初始化之后执行;
查看前置方法的源码,发现他就是循环遍历所有的 BeanPostProcessor
,然后依次执行,后置方法同理。
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
而且这两个方法和我们写实现类重写的两个方法同名,作用也一致,这里是 Spring
使用了代理模式进行了增强,我们重写的部分就是增强的内容。
注:
Spring 底层很多地方都使用了 BeanPostProcessor
及其子类,如 AutowiredAnnotationBeanPostProcessor
,就是 @Autowired
注解。
- Go语言同步(Synchronization)
- Android开发必备知识:为什么说Kotlin值得一试
- Go语言实现冒泡排序、选择排序、快速排序及插入排序的方法
- Go语言排序与接口实例分析
- 从 Android 静音看正确的查找 bug 的姿势
- GO语言并发编程之互斥锁、读写锁详解
- 浅析Go语言中的Range关键字
- Go语言使用sort包对任意类型元素的集合进行排序的方法
- 优化Linux的内核参数来提高服务器并发处理能力
- 浅析 Android 的窗口
- Golang同步:锁的使用案例详解
- Android 开发绕不过的坑:你的 Bitmap 究竟占多大内存?
- 高性能网络编程7--tcp连接的内存使用
- 从websocket看go的应用
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释