JSR250
提供的两个注解;BeanPostProcessor
后置处理器;可以使用 @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
有一个抽象方法 afterPropertiesSet
,DisposableBean
有一个抽象方法 destroy
,分别代表 init
和 destroy
方法。
继承之后可以重写这两个方法:
public void destroy() {
System.out.println("汽车销毁了...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("汽车初始化了...");
}
效果也和上面一样,这样就不用再使用 @Bean 指定初始化和销毁方法了。
注意:
这两个注解都是 JSR250
提供的注解:
@PostConstruct
: 在 bean 创建完成并且属性赋完值的时候调用方法;@PreDestroy
: 在容器销毁 bean 之前通知我们进行清理操作;该注解在实体类上的方法使用:
/**
* 对象创建并赋值之后调用
*/
@PostConstruct
public void init() {
System.out.println("汽车初始化...");
}
/**
* 容器移除对象之前调用
*/
@PreDestroy
public void destroy() {
System.out.println("汽车销毁了...");
}
该类的作用就是在 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 的执行原理:
这是截取的一段源代码,出自 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
注解。