這次的内容是上圖中的第06步。
前言
通過前面幾篇文章的介紹,在整個容器重新整理過程中現在已經有了如下元件:
先來看看前面幾篇文章都做了什麼:
`01-prepareRefresh()`: `earlyApplicationListeners`、`applicationListeners` 、`initPropertySources()`、`validateRequiredProperties`
`02-obtainFreshBeanFactory()`: `refreshBeanFactory`
`03-prepareBeanFactory()`: `ignoreDependencyInterface`、`setBeanExpressionResolver`、`registerResolvableDependency`、`Environment`
`04-postProcessBeanFactory()`: 具體實作類的特殊邏輯(`Servlet` 等)
`05-invokeBeanFactoryPostProcessors()`: 可能發生的對 `BeanFactory/BeanDefinitionRegistry` 的修改操作
也就是說,現在的 BeanFactory 已經完全準備好了,通過正常途徑已經無法修改 BeanFactory 了。
接下來就要開始考慮單例 Bean 的初始化了,但是在此之前,還有好多的準備工作。
第一個準備工作就是本文要說的 registerBeanPostProcessors()。
registerBeanPostProcessors() 隻是注冊各種 BeanPostProcessor,還遠遠沒到 BeanPostProcessor 執行的時候。
前置知識
看 registerBeanPostProcessors() 方法的名字就是要注冊 BeanPostProcessor 了,那麼先來了解一下 BeanPostProcessor 是什麼。
BeanPostProcessor 是一個鈎子函數,用來修改新建立的 Bean 執行個體,比如 檢測标記在 Bean 上的标記接口或用代理對象包裝 Bean。BeanPostProcessor 還有一系列的擴充子接口。
下面就介紹幾種常見的 BeanPostProcessor。
BeanPostProcessor
public interface BeanPostProcessor {
/**
* 在任何 「Bean初始化方法」(比如說InitializingBean#afterPropertiesSet) 回調之前, 将該 BeanPostProcessor 應用于一個給定的新的Bean執行個體.
*
* 此處傳入的 Bean 已經經過 populateBean 填充屬性了.
* 傳回的 bean 執行個體可能是對原始bean的包裝.
* 預設實作: 原樣傳回給定的 Bean
*
* 如果傳回 null, 則不會調用後續的 BeanPostProcessors.
*
* @return 原始對象或者對原始對象的包裝;
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* 在任何 「Bean初始化方法」(比如說InitializingBean#afterPropertiesSet) 回調之後, 将該 BeanPostProcessor 應用于一個給定的新的Bean執行個體.
*
* 此處傳入的 Bean 已經經過 populateBean 填充屬性了.
* 傳回的 bean 執行個體可能是對原始bean的包裝.
*
* 對于 FactoryBean 的情況而言,該回調方法既可以對 FactoryBean 執行個體本身回調, 也可以對 FactoryBean 傳回的對象回調(從 Spring 2.0 開始).
* 具體實作可以自己決定是否回調 FactoryBean 執行個體 或/和 FactoryBean 傳回的執行個體.
*
* 與其他的回調方法不同, 該回調方法也可以被 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 觸發
*
* 預設實作: 原樣傳回給定的 Bean
*
* 如果傳回 null, 則不會調用後續的 BeanPostProcessors.
*
* @return 原始對象或者對原始對象的包裝;
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,主要擴充了如下的方法:
- 擴充了一個在 Bean 執行個體化 之前的回調
- 擴充了一個在 Bean 執行個體化 之後, 但在 Bean 填充屬性或自動裝配發生之前的回調
一般用于攔截特定目标對象的預設執行個體化,比如建立(池化、懶加載等)代理對象。或者實作特定的注入政策,比如字段注入。
該接口是一個特殊接口,主要在架構内部使用。一般場景,建議盡可能實作簡單的 BeanPostProcessor 接口。而不是使用該接口。
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* 在目标bean執行個體化之前回調該BeanPostProcessor.
*
* 傳回的bean對象可能是代理對象,而不是目标bean,進而攔截了目标bean的預設執行個體化.
*
* 如果該方法傳回了非空對象,則目前bean的建立過程将被短路.
* 短路之後唯一會被進一步調用的是來自BeanPostProcessors的postProcessAfterInitialization方法。
*
* 預設實作: 傳回 null
*
* @return 代理對象 或 傳回null以繼續Bean的預設執行個體化流程
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
/**
* 回調時機: Bean 被[執行個體化]之後(構造器或工廠方法),但在spring填充屬性或自動裝配之前
*
* 這裡是實作使用者自定義字段注入的完美時機,剛好在 spring 的自動注入之前.
*
* 預設實作: return true
*
* @return true: 表示應該給目前Bean填充屬性;
* false: 對目前Bean的屬性填充應該被跳過;
*
* 傳回false還會阻止在目前bean執行個體上回調任何後續的InstantiationAwareBeanPostProcessor執行個體。
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* 在工廠将給定的屬性值應用于給定的bean之前,對目前Bean進行處理
*
* 如果具體實作類提供來自定義的postProcessPropertyValues實作,則應傳回null(預設值),否則傳回pvs
*
* @return the actual property values to apply to the given bean (can be the passed-in
* PropertyValues instance), or {@code null} which proceeds with the existing properties
* but specifically continues with a call to {@link #postProcessPropertyValues}
* (requiring initialized {@code PropertyDescriptor}s for the current bean class)
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
/**
* Post-process the given property values before the factory applies them
* to the given bean. Allows for checking whether all dependencies have been
* satisfied, for example based on a "Required" annotation on bean property setters.
* <p>Also allows for replacing the property values to apply, typically through
* creating a new MutablePropertyValues instance based on the original PropertyValues,
* adding or removing specific values.
* <p>The default implementation returns the given {@code pvs} as-is.
* @param pvs the property values that the factory is about to apply (never {@code null})
* @param pds the relevant property descriptors for the target bean (with ignored
* dependency types - which the factory handles specifically - already filtered out)
* @param bean the bean instance created, but whose properties have not yet been set
* @param beanName the name of the bean
* @return the actual property values to apply to the given bean (can be the passed-in
* PropertyValues instance), or {@code null} to skip property population
* @throws org.springframework.beans.BeansException in case of errors
* @see #postProcessProperties
* @see org.springframework.beans.MutablePropertyValues
* @deprecated as of 5.1, in favor of {@link #postProcessProperties(PropertyValues, Object, String)}
*/
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
DestructionAwareBeanPostProcessor
DestructionAwareBeanPostProcessor 是 Bean 被銷毀之前的回調接口。所謂的銷毀指的是: DisposableBean.destroy()、 destroy-method 等。
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
/**
* Bean 被銷毀之前回調
*/
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
/**
* 目前 Bean 是否需要被銷毀
* @since 4.3
*/
default boolean requiresDestruction(Object bean) {
return true;
}
}
registerBeanPostProcessors
這一步就是給 BeanFactory 中注冊各種 BeanPostProcessor,那麼最終注冊到哪裡去了呢?
addBeanPostProcessor
看看下面的 addBeanPostProcessors() 和 addBeanPostProcessor() 方法就明白了。
值得注意的是,這兩個方法雖然名字看起來是 add,但是實際上他的作用應該是: removeAndAddToLast 的意思,就是每次先删掉之前的,再将新增的放到最後。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();
public void addBeanPostProcessors(Collection<? extends BeanPostProcessor> beanPostProcessors) {
this.beanPostProcessors.removeAll(beanPostProcessors);
this.beanPostProcessors.addAll(beanPostProcessors);
}
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
}
繼續看 registerBeanPostProcessors(),實際上最終是委托給了 PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext) 這個工具方法。
源碼流程
方法剛開始還是和上一篇介紹的 invokeBeanFactoryPostProcessors 一樣,來了一大波提示資訊,大概意思是:
這個方法看起來寫的很啰嗦,好像很容易優化。但是在你優化之前先瞅瞅 github 已經被拒絕的的 PR 清單……
final class PostProcessorRegistrationDelegate {
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
// 這裡依然是小心翼翼僅僅擷取了 BeanPostProcessor 類型的 beanName,還不能調用 getBean()
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
// beanFactory.getBeanPostProcessorCount(): 目前 BeanFactory 中已經存在的 BeanPostProcessor 數量
// +1: 加的 1 就是 `BeanPostProcessorChecker` 自己
// postProcessorNames.length: 指的是在下面一大波循環中要新增到 BeanFactory 中的 BeanPostProcessor
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// BeanPostProcessorChecker就是來檢測: 在 BeanPostProcessor 初始化的過程中有沒有導緻普通的 Bean 初始化
// 如果有: 就列印一堆資訊提醒你, 有 Bean 被過早初始化了
// 為什麼要提醒: 因為現在還在建立 BeanPostProcessor,
// 但是這個過程中你突然建立了一個普通 Bean,
// 那麼你這個過早被建立的普通 Bean 可能無法被 BeanPostProcessor 增強(比較 BeanPostProcessor 自己都還在建立過程中呢)
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 還是老套路: 将 BeanPostProcessor 分類(4大類)
// 需要注意的是第1類和第2類是通過 getBean 建立出來的執行個體,其他兩類都是 beanName(避免過早執行個體化)
// 需要注意的是第1類和第2類是通過 getBean 建立出來的執行個體,其他兩類都是 beanName(避免過早執行個體化)
// 需要注意的是第1類和第2類是通過 getBean 建立出來的執行個體,其他兩類都是 beanName(避免過早執行個體化)
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 第 1 類: 實作了 PriorityOrdered 接口的
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 實作了 `PriorityOrdered` 接口的 BeanPostProcessor 還有個細分的類型
// 第 2 類: MergedBeanDefinitionPostProcessor 類型的 BeanPostProcessor
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// 第 3 類: 實作了 Ordered 接口的
List<String> orderedPostProcessorNames = new ArrayList<>();
// 第 4 類: 普通的 BeanPostProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// 第 1 類
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 這裡是通過 getBean 真真正正建立了 BeanPostProcessor 類型的 Bean
// 而不是 beanName
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
// 第 2 類
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 第 3 類
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
// 第 4 類
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 經過上面的循環,已經給各種 BeanPostProcessor 分好類了
// 下面就是按照不同類型的優先級注冊到 BeanPostProcessor 中
// 1. 先注冊實作了 `PriorityOrdered` 接口的 BeanPostProcessor
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 其實就是調用了 beanFactory.addBeanPostProcessor 給目前 BeanFactory 中新增 BeanPostProcessor
// 作用是: 将給定的 BeanPostProcessor 添加到最後
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 2. 注冊實作了 `Ordered` 接口的 BeanPostProcessor
// Next, register the BeanPostProcessors that implement Ordered.
// 先通過 getBean 建立執行個體,然後注冊
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 3. 普通的 BeanPostProcessor
// Now, register all regular BeanPostProcessors.
// 先通過 getBean 建立執行個體,然後注冊
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 4. 注冊 internalPostProcessors
// 所謂的 `internalPostProcessors` 指的就是 `MergedBeanDefinitionPostProcessor` 這種子接口
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 5. 将 `ApplicationListenerDetector` 移動到最後
// 就是來處理實作了 `ApplicationListener` 這種事件接口的 Bean 的
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
}
BeanPostProcessorChecker
現在回頭再看看 BeanPostProcessorChecker。他是用來檢測:在 BeanPostProcessor 的初始化過程中是不是有其他普通的 Bean 被過早初始化了。
- 什麼叫普通的 Bean: 除了 BeanPostProcessor 類型和 BeanDefinition.role == RootBeanDefinition.ROLE_INFRASTRUCTURE 的 Bean 都是普通 Bean
- 什麼叫過早初始化: 一個普通 Bean 的正常建立流程應該經過一系列的 BeanPostProcessor 處理,但是現在 BeanPostProcessor 自己還在初始化過程中呢。這時候如果初始化一個普通的 Bean ,就無法保證這個普通 Bean 被所有的 BeanPostProcessor 處理,也就是說 Bean 被提前初始化了。
成員變量 beanPostProcessorTargetCount 什麼意思呢?
其實就是上面代碼中的 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; 這一行。
- beanFactory.getBeanPostProcessorCount(): 指的是 BeanFactory 中已經存在的 BeanPostProcessor 執行個體的個數
- +1: 指的是 BeanPostProcessorChecker 自己
- postProcessorNames.length: 指的是經過上面的幾波循環之後新增了多少 BeanPostProcessor 的執行個體
private static final class BeanPostProcessorChecker implements BeanPostProcessor {
private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class);
private final ConfigurableListableBeanFactory beanFactory;
private final int beanPostProcessorTargetCount;
public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {
this.beanFactory = beanFactory;
this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 除了 BeanPostProcessor 類型 和 BeanDefinition.role == `RootBeanDefinition.ROLE_INFRASTRUCTURE`
if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
// 這個小于判斷如果成立的話 就說明現在還有 `BeanPostProcessor` 沒有執行個體化完成
this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
if (logger.isInfoEnabled()) {
logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
"] is not eligible for getting processed by all BeanPostProcessors " +
"(for example: not eligible for auto-proxying)");
}
}
return bean;
}
private boolean isInfrastructureBean(@Nullable String beanName) {
if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);
return (bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE);
}
return false;
}
}
小節
通過這一步,所有的 BeanPostProcessor 的執行個體已經被建立了。并且都被注冊到了 BeanFactory 中了。
但是需要注意的是,這裡僅僅是 BeanPostProcessor 自己的執行個體化和注冊,還沒到 BeanPostProcessor 執行的時候呢。
後續的 Bean 建立過程中,這些 BeanPostProcessor 就可以發揮作用了。