文章目錄
- 一、前言
- 二、BeanPostProcessor
- 三、基本介紹
- 四、源碼中的調用場景
- 1. InstantiationAwareBeanPostProcessor
- 1.1. IBP.postProcessBeforeInstantiation
- 1.2. IBP.postProcessAfterInstantiation & IBP.postProcessProperties & IBP.postProcessPropertyValues
- 2. BeanPostProcessor
- 3. SmartInstantiationAwareBeanPostProcessor
一、前言
本文是 Spring源碼分析:單例bean的獲取 - createBean 的衍生文章。主要是因爲本人菜雞,在分析源碼的過程中還有一些其他的內容不理解,故開設衍生篇來完善內容以學習。
二、BeanPostProcessor
所謂的 BeanPostProcessor
翻譯過來就是Bean後處理器。實際上Spring還有一類後處理器BeanFactoryPostProcessor
,源碼還沒看到這,暫不分析。
1. 什麼是 BeanPostProcessor
BeanPostProcessor
是 Spring提供給我們的一個非常重要的擴展接口,並且Spring內部的很多功能也是通過 BeanPostProcessor 來完成的(目前看到最典型的就是 AnnotationAwareAspectJAutoProxyCreator
的 注入)。
2. BeanPostProcessor 的種類
BeanPostProcessor
在Spring 中的子類非常多(idea 顯是有46個),比如
InstantiationAwareBeanPostProcessorAdapter
: 在Spring 的bean加載過程中起了非常重要的作用AnnotationAwareAspectJAutoProxyCreator
: bean 創建過程中的 屬性注入時起作用AspectJAwareAdvisorAutoProxyCreator
: Aspect 的 AOP 功能實現也全仰仗BeanPostProcessor 的特性。
3. BeanPostProcessor 的註冊
BeanPostProcessor 的註冊是在 AbstractApplicationContext#registerBeanPostProcessors 中完成的。在Spring 剛剛啓動時候,會調用refresh() 方法,隨機調用registerBeanPostProcessors 方法。 在這個方法中,Spring 將各處的BeanPostProcessor 的實現類 註冊到 BeanFactory.beanPostProcessors 屬性中,後面獲取BeanPostProcessor 時直接通過該屬性獲取。
三、基本介紹
日常使用中,我們一般編寫一個類來實現 BeanPostProcessor
或者 InstantiationAwareBeanPostProcessor
接口,根據每個方法的調用時機,來完成響應的工作。
下面介紹一下接口方法,這裏通過 InstantiationAwareBeanPostProcessor
接口來介紹 。InstantiationAwareBeanPostProcessor
是 BeanPostProcessor
的子接口,在 BeanPostProcessor
基礎上又擴展了三個方法。
@Component
public class DemoPostProcesser implements InstantiationAwareBeanPostProcessor {
//InstantiationAwareBeanPostProcessor 提供的方法, 在 Class<T> -> T 的轉換過程中
// 此時bean還沒創建,可以通過這方法代替 Spring 容器創建的方法
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessBeforeInstantiation ### 1");
return null;
}
//InstantiationAwareBeanPostProcessor 提供的方法, 返回的值代表是否需要繼續注入屬性,
// 如果返回true,則會調用postProcessProperties和postProcessPropertyValues 來注入屬性
// 此時bean已經創建,屬性尚未注入
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessAfterInstantiation ### 2");
return true;
}
//InstantiationAwareBeanPostProcessor 提供的方法,可以在這個方法中進行bean屬性的注入,Aop 就是在此方法中進行了代理的創建
// 只有postProcessAfterInstantiation 返回true 時纔會調用
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessProperties ### 3");
return pvs;
}
//InstantiationAwareBeanPostProcessor 提供的方法,可以在這個方法中進行bean屬性的注入, 這個方法已經過時,使用postProcessProperties 代理
// 只有postProcessAfterInstantiation 返回true 時 且 postProcessProperties 返回 null 時調用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessPropertyValues ### 4");
return pvs;
}
// BeanPostProcessor 提供的方法,在bean初始化前調用,這時候的bean大體已經創建完成了,在完成一些其他屬性的注入
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessBeforeInitialization ### 5");
return bean;
}
// BeanPostProcessor 提供的方法,在bean初始化後調用,這時候的bean 已經創建完成了
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessAfterInitialization ### 6");
return bean;
}
}
其調用順序也和標註相同
注意:
這裏可以看到 postProcessPropertyValues
方法並沒有調用,因爲對於一個 過時的方法 沒必要必須要調用它,前面也提到 postProcessAfterInstantiation
返回true 並且 postProcessProperties
返回不爲null 纔會調用該方法,這裏postProcessProperties
返回不爲null ,所以不會調用postProcessPropertyValues
方法
四、源碼中的調用場景
下面爲了方便描述,進行一些簡化寫法,爲了後面描述方便
BP : BeanPostProcessor
IBP : InstantiationAwareBeanPostProcessor
SBP : SmartInstantiationAwareBeanPostProcessor
其結構如下圖:
這裏就不具體貼出多少代碼。簡單解釋一下調用場景
Spring 在啓動過程中,會將所有實現了 BeanPostProcessor 接口的子類保存到 AbstractBeanFactory 中的 beanPostProcessors 集合中,如下:
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
在適當的時候(這個適當的時候就根據 每個接口方法定義的意義來判斷), Spring會獲取 所有的BeanPostProcessor 子類集合,即 beanPostProcessors ,經過類型過濾後,調用對應的方法。比如,就是對 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
方法的調用流程(其餘方法的調用也類似):
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 因爲只有 InstantiationAwareBeanPostProcessor 類型纔有postProcessBeforeInstantiation 方法,所以這裏要判斷一下是不是 InstantiationAwareBeanPostProcessor 類型
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
1. InstantiationAwareBeanPostProcessor
下面來介紹在 Spring 創建流程中 每個方法的實際調用位置:
1.1. IBP.postProcessBeforeInstantiation
IBP.postProcessBeforeInstantiation
方法在 Bean 創建 之前調用,我所理解的目的是替換Spring 容器創建bean, 當 IBP.postProcessBeforeInstantiation
返回不爲null時,則不會再通過Spring 創建bean,而是使用 IBP.postProcessBeforeInstantiation
返回的bean。
...
// 該方法中 調用了postProcessBeforeInstantiation 方法,並且可能調用 postProcessAfterInitialization 方法
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
...
// 真正去創建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
...
resolveBeforeInstantiation
方法內容如下,可以看到 當 applyBeanPostProcessorsBeforeInstantiation
方法(applyBeanPostProcessorsBeforeInstantiation
調用了 postProcessBeforeInstantiation
方法) 返回值不爲 null,則會調用 postProcessAfterInstantiation
方法。因爲這裏bean返回不爲null,則代表bean創建成功了,就會調用創建成功後的方法,即 postProcessAfterInstantiation
。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
這裏需要注意,在 resolveBeforeInstantiation
方法中,當 bean != null
時 調用了 applyBeanPostProcessorsAfterInitialization
方法,即 BP.postProcessAfterInitialization
方法。這是因爲如果 bean != null
, 則說明 bean 的創建已經完成,那麼這裏則是最後調用bean 的後置處理的機會,即調用BP.postProcessAfterInitialization
方法的最後機會。
1.2. IBP.postProcessAfterInstantiation & IBP.postProcessProperties & IBP.postProcessPropertyValues
IBP.postProcessAfterInstantiation
、IBP.postProcessProperties
、 IBP.postProcessPropertyValues
的調用場景只有一處,在AbstractAutowireCapableBeanFactory#populateBean
方法中,此時bean已經創建完成,正在進行屬性注入。而 IBP.postProcessAfterInstantiation
的返回值決定是否繼續注入
大致代碼如下
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
// 調用 postProcessAfterInstantiation 方法嗎,如果返回false,直接return;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
...
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 調用 postProcessProperties 注入屬性
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 調用 postProcessPropertyValues 注入屬性
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
...
}
通過代碼我們可以比較清楚的看到整體邏輯:
- 若
IBP.postProcessAfterInstantiation
返回true,纔會執行下面步驟 - 調用
IBP.postProcessProperties
注入屬性, - 若
IBP.postProcessProperties
返回爲null,纔會執行下面步驟 - 調用
IBP.postProcessPropertyValues
注入屬性
2. BeanPostProcessor
2.1. BP.postProcessBeforeInitialization
BP.postProcessBeforeInitialization
調用時機是bean已經創建完成,但是尚未初始化,即一些屬性配置尚未完成(我看到的就一個 init-method 的配置)。使用場景也只有一處,即
AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
。
程序走到這裏,代表 resolveBeforeInstantiation
方法 中的 IBP.postProcessBeforeInstantiation
並未代理 bean的創建,在這裏則是由Spring 創建的bean的時候來調用。
代碼如下,
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
....
// 調用 BP.postProcessBeforeInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 初始化屬性,貌似就初始化了 一個 init-method
...
if (mbd == null || !mbd.isSynthetic()) {
// 調用 BP.postProcessAfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
2.2. BP.postProcessAfterInitialization
IBP.postProcessAfterInstantiation
的調用都被封裝到 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
方法中。
而applyBeanPostProcessorsAfterInitialization
方法的調用
applyBeanPostProcessorsAfterInitialization
方法在下面三個方法中調用:
- AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
- AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
- AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean
2.2.1 resolveBeforeInstantiation
resolveBeforeInstantiation
方法的調用有如下三處
-
AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[]) 這裏的調用實際上就是上面講的 IBP.postProcessBeforeInstantiation 的調用後續,所以這裏不再重複
-
AbstractAutowireCapableBeanFactory#getSingletonFactoryBeanForTypeCheck
-
AbstractAutowireCapableBeanFactory#getNonSingletonFactoryBeanForTypeCheck
2.2.2 initializeBean
上面介紹 BP.postProcessBeforeInitialization
的時候已經說了,所以這裏不再贅述
2.2.3 postProcessObjectFromFactoryBean
在 FactoryBeanRegistrySupport#getObjectFromFactoryBean
中調用,在從 FactoryBean 中獲取 bean時調用,在此調用可以替換掉 FactoryBean 中的返回的bean。
3. SmartInstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor
在 IBP 之上又擴展了三個方法,不過我們一般不會使用,所以這裏簡單敘述一下SmartInstantiationAwareBeanPostProcessor
三個方法的作用
-
Class<?> predictBeanType(Class<?> beanClass, String beanName) : 在進行bean類型匹配時調用,返回值和期望值進行匹配。
-
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) : 在 Spring 加載bean 的時候,判斷是否需要通過構造注入時,如果返回的值不爲空,則進行有參構造注入。
// determineConstructorsFromBeanPostProcessors 中調用了 determineCandidateConstructors 方法,如果ctors != null, 則進行有參構造autowireConstructor Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); }
-
Object getEarlyBeanReference(Object bean, String beanName) : 在 Spring 解決循環依賴時候使用,返回的值將作爲ObjectFactory 的 保存的Object,用於循環依賴的提前暴露。
if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // getEarlyBeanReference 的返回值作爲 ObjectFactory 的返回值保存到singletonFactories緩存中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); }
最後,附一張自己畫的調用流程圖,由於完全有本人自己閱讀繪製,可能會出現些許紕漏,如果發現,麻煩指正,謝謝。
以上:內容部分參考
《Spring源碼深度解析》
如有侵擾,聯繫刪除。 內容僅用於自我記錄學習使用。如有錯誤,歡迎指正