引言
如果對
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;
}
具體在什麼時候調用這兩個方法呢?方法會在每一個bean對象的初始化方法調用之前回調
postProcessBeforeInitialization
方法會在每個bean對象的初始化方法調用之後被回調
postProcessAfterInitialization
自定義BeanPostProcessor
由上面
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
的執行是在容器的重新整理過程中,容器重新整理對象具體的方法為:
在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
的子類來實作。
BeanPostProcessor
的繼承結構如下:

常見BeanPostProcessor分析
下圖是debug過程中,
ApplicationContext
對象中的包含的
BeanPostProcessor
。具體包含哪些
BeanPostProcessor
與具體應用程式相關,除了下标3中的
MyBeanPostProcessor
為自定義的
BeanPostProcessor
,其餘均為Spring自帶的
BeanPostProcessor
。
下面來分析一下
ApplicationContextAwareProcessor
和
AutowiredAnnotationProcessor
的執行原理。
ApplicationContextAwareProcessor
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
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
,其具體内容如下
這個方法調用就是根據反射執行init方法
InstantiationAwareBeanPostProcessor
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