如果对
BeanPostProcessor
的使用不是很了解的,可以参考另一篇文章:https://blog.csdn.net/zxd1435513775/article/details/83019572
BeanPostProcessor
也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中会回调BeanPostProcessor
中定义的两个方法。BeanPostProcessor
源码如下:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
具体在什么时候调用这两个方法呢?
postProcessBeforeInitialization
方法会在每一个bean对象的初始化方法调用之前回调
postProcessAfterInitialization
方法会在每个bean对象的初始化方法调用之后被回调
由上面BeanPostProcessor
源码可以看到它两个方法的参数都相同,其中:
第一个参数Object bean表示当前正在初始化的bean对象。
两个方法都返回Object类型的实例,返回值既可以是将入参Object bean原封不动的返回出去,也可以对当前bean进行包装再返回
来看看下面的自定义BeanPostProcessor
// 后置处理器:在每一个bean初始化前后进行处理工作,需要将后置处理器加入到容器中
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization..."+beanName+"..."+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization..."+beanName+"..."+bean);
return bean;
}
}
Spring容器中加入MyBeanPostProcessor之后,针对容器中每个创建的Bean对象,既包括Spring自身创建的Bean,也包括应用程序创建的Bean,都会回调
postProcessBeforeInitialization
和postProcessAfterInitialization
方法。
BeanPostProcessor
的执行是在容器的刷新过程中,容器刷新对象具体的方法为:
AbstractApplicationContext.refresh()
在refresh方法执行的调用栈中会去调用AbstractAutowireCapableBeanFactory.doCreateBean()
方法,该方法节选源码如下
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用postProcessBeforeInitialization方法
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()) {
// 调用postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
看到在调用初始化方法前后会分别调用applyBeanPostProcessorsBeforeInitialization()
和applyBeanPostProcessorsAfterInitialization()
。
applyBeanPostProcessorsBeforeInitialization()
方法的源码如下:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
// 会拿到所有的BeanPostProcessor,进行逐一遍历
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
// 会拿到所有的BeanPostProcessor,进行逐一遍历
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
可以看到其逻辑为:
遍历得到容器中所有的BeanPostProcessor
,然后执行postProcessBeforeInitialization
,一但返回null,就跳出for循环,不执行后面的BeanPostProcessor.postProcessorsBeforeInitialization()
。
也就是说,如果返回的是null,那么我们通过getBean方法将得不到目标Bean。
applyBeanPostProcessorsAfterInitialization()
方法的逻辑和上面一致,Spring底层的很多功能特性都是借助BeanPostProcessor
的子类来实现。
下图是debug过程中,ApplicationContext
对象中的包含的BeanPostProcessor
。具体包含哪些BeanPostProcessor
与具体应用程序相关,除了下标3中的MyBeanPostProcessor
为自定义的BeanPostProcessor
,其余均为Spring自带的BeanPostProcessor
。
下面来分析一下ApplicationContextAwareProcessor
和AutowiredAnnotationProcessor
的执行原理。
ApplicationContextAwareProcessor
后置处理器的作用是:当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext对象
@Component
public class Car implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Car(){
System.out.println("car instance...");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContextAware...setApplicationContext()");
this.applicationContext = applicationContext;
}
}
那Car是如何通过实现ApplicationContextAware
接口就能获得ApplicationContext
对象呢?
答案:通过ApplicationContextAwareProcessor
后置处理器来实现,下面来看看ApplicationContextAwareProcessor
的源码
// 实现BeanPostProcessor接口
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
// 实现BeanPostProcessor接口中的postProcessBeforeInitialization
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
// 这里bean是Car,它实现了ApplicationContextAware接口
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
// 如果实现了ApplicationContextAware接口,就是执行下面方法
invokeAwareInterfaces(bean);
}
return bean;
}
// 这里bean是Car
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
// 此条件成立
if (bean instanceof ApplicationContextAware) {
// 会执行这里回调car重写的setApplicationContext方法,然后将this.applicationContext注入给Car
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
// 实现BeanPostProcessor接口中的postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
InitDestroyAnnotationBeanPostProcessor
后置处理器是用来处理自定义的初始化方法和销毁方法。
Spring中提供了3种自定义初始化和销毁方法:
通过@Bean
注解指定init-method
和destroy-method
属性
Bean实现InitializingBean
(定义初始化逻辑),DisposableBean
(定义销毁逻辑)两个接口
@PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化方法@PreDestroy,在容器销毁bean之前通知我们进行清理工作
InitDestroyAnnotationBeanPostProcessor
的作用就是让第3种方式生效。
先看看如何使用@PostConstruct
和@PreDestroy
注解。
@Component
public class Car {
public Car(){
System.out.println("car instance...");
}
// 自定义的初始化方法
@PostConstruct
public void init(){
System.out.println("car ... init...");
}
// 自定义的销毁方法
@PreDestroy
public void detory(){
System.out.println("car ... detory...");
}
}
InitDestroyAnnotationBeanPostProcessor
会在Bean创建的时候通过反射的方式查找包含@PostConstruct
和@PreDestroy
注解的方法,然后再通过反射执行方法。
我们来看看InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()
的源码
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 获取bean的metadata
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 执行@PostConstruct指定的init方法
metadata.invokeInitMethods(bean, beanName);
} catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
metadata
中已经解析出initMethods
和destroyMethods
,其具体内容如下
metadata.invokeInitMethods(bean, beanName)
这个方法调用就是根据反射执行init方法
InstantiationAwareBeanPostProcessor
也是个接口,它是BeanPostProcessor
的子接口
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
//实例化Bean之前调用
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
//实例化Bean之后调用
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
//设置Bean对象中的某个属性时调用
PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
这两个接口的功能基本类似,不过要注意
InstantiationAwareBeanPostProcessor
和BeanPostProcessor
的方法名区别
InstantiationAwareBeanPostProcessor
中是Instantiation
,BeanPostProcessor
是Initialization