上篇文章我們分析了
invokeBeanFactoryPostProcessors()
方法的實現,主要是BeanFactory
的BeanDefinition
定義在實例化之前做一些前置操作。接下來本文來看看registerBeanPostProcessors()
的實現,上篇文章留了一個疑問,大家是否還記得?我們在本篇文章揭曉答案,本篇先來解讀源碼,後面附上測試用例。
回到
AbstractApplicationContext.refresh()
方法的registerBeanPostProcessors()
地方,我們來看看實現,從方法中可以看出,調用了PostProcessorRegistrationDelegate
類的靜態方法。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
PostProcessorRegistrationDelegate.registerBeanPostProcessors
方法用於註冊所有BeanPostProcessor
實例(該方法比較長,但是流程很清晰,耐心開完)。看源碼前首先需要明白兩個類:
BeanPostProcessor
: 一切BeanPostProcessor
實例都需要直接或間接該接口。MergedBeanDefinitionPostProcessor
: 是一個接口,實現了BeanPostProcessor
接口,並給出了一個方法。所以實現了該接口的類比實現了BeanPostProcessor
類的優先級更高,功能更豐富。
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// Step1:獲取所有直接或間接實現了BeanPostProcessor接口的BeanDefinition對應的processor名字。內部實現見源碼分析3
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.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// Step2:添加一個BeanPostProcessor檢查器,該檢查器的作用:是在創建BeanPostProcessor時記錄日誌、創建BeanPostProcessor發生異常時記錄日誌等等操作。
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// Step3:存放實現了PriorityOrdered接口的BeanPostProcessor,其優先級最高。
// PriorityOrdered接口作用:用於對BeanPostProcessor進行優先級排序的。和上一篇關於BeanFactoryPostProcessor的排序功能一樣。
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// Step4:存放內部實現的BeanPostProcessor。
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// Step5:存放實現了Ordered接口的BeanPostProcessor,其優先級低於PriorityOrdered接口
// Ordered接口作用:也是排序功能。
List<String> orderedPostProcessorNames = new ArrayList<>();
// Step6:存放除去內部的和有優先級的BeanPostProcessor後,剩餘的BeanPostProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// Step7:遍歷BeanPostProcessor對應的名字,進行分堆和創建Bean實例操作。關於創建Bean實例在後面創建Bean實例專門介紹,這裏不展開。
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
// Step8:對PriorityOrdered相關的BeanPostProcessor進行排序操作,排序的依據是重寫了PriorityOrdered的getOrder的返回值
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Step9:將排序後的BeanPostProcessor一次註冊到BeanFactory裏面。
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
// Step10:遍歷實現了Ordered接口的BeanPostProcessor,如果改processor實現了MergedBeanDefinitionPostProcessor接口,將其加入到內部的BeanPostProcessor集合裏面。
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// Step11:排序
sortPostProcessors(orderedPostProcessors, beanFactory);
// Step12:註冊
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
// Step13:對無優先級的BeanPostProcessor進行遍歷,將實現了MergedBeanDefinitionPostProcessor接口的加入到內部BeanPostProcessor的集合中
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// Step14:沒有先後順序,一次註冊這些Bean實例到BeanFactory裏面。
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
// Step15:最後對所有的內部BeanPostProcessor實例進行排序操作,並將其註冊到BeanFactory裏面。
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// Step16:對BeanFactory添加一個一個全局的監聽器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
我們來看下
BeanPostProcessor
對應的beanName
是怎麼獲取到的。
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
// Step1:當前BeanFactory是否凍結,凍結返回true(就是說當前BeanFactory的BeanDefinition定義是否不可以被修改)
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
// Step2:從當前BeanFactory的緩存裏面獲取對應的BeanPostProcessor名字。如果有直接返回(在Spring源碼中大量用到了這種緩存機制來提升Spring容器初始化的速度)
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
// Step3:都沒有取到,則根據type去加載相應的名字
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
來看看根據
type
如果獲取到對應的BeanPostProcessor
名字,這裏稍微比較複雜一點,歸納一下其實就是遍歷所有的beanName
,然後拿type
去匹配,如果能匹配的上就認爲是目標的BeanPostProcessor
對應的baneName
。
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<>();
// Check all bean definitions.
// Step1:遍歷當前BeanFactory裏面所有的beanNames
for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name
// is not defined as alias for some other bean.
// Setp1.1:判斷當前beanName是否是別名,所以if裏面的邏輯是針對非別名的beanName處理。
if (!isAlias(beanName)) {
try {
// Step1.1.1:根據beanName獲取對應的BeanDefinition定義,具體邏輯之前介紹過,在這裏就不展開了。
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
// Step1.1.2:檢查BeanDefinition定義是否完整。即當前BeanDefinition定義是:非抽象的 && (提前加載 || (有對應的BeanClass || 非懶加載 || 允許提前加載bean)&& 是否提前初始化指定類型的bean)
// 總結大概意思就是當前BeanDefinition定義是非抽象的且可以提前加載
if (!mbd.isAbstract() && (allowEagerInit ||
(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// In case of FactoryBean, match object created by FactoryBean.
// Setp1.1.2.1:根據beanName和對應的BeanDefinition定義判斷是否是一個FactoryBean。
boolean isFactoryBean = isFactoryBean(beanName, mbd);
// Step1.1.2.2:返回此BeanDefinition被修飾的BeanDefinitionHolder對象。
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
// Step1.1.2.3:判斷beanName和對應的BeanDefinition是否匹配
boolean matchFound =
(allowEagerInit || !isFactoryBean ||
(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
(includeNonSingletons ||
(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
isTypeMatch(beanName, type);
// Step1.1.2.4:沒匹配到 %% 是BeanFactory,則添加BeanFactory的前綴,在匹配一次。
if (!matchFound && isFactoryBean) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
}
// Step1.1.2.5:匹配到則將beanName加到結果集中
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
catch (BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
}
}
// Check manually registered singletons too.
// Step2:檢查手動註冊的單例Bean
for (String beanName : this.manualSingletonNames) {
try {
// In case of FactoryBean, match object created by FactoryBean.
// Step2.1:是一個FactoryBean並且匹配到了,則加入到結果集中
if (isFactoryBean(beanName)) {
if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
result.add(beanName);
// Match found for this bean: do not match FactoryBean itself anymore.
continue;
}
// In case of FactoryBean, try to match FactoryBean itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
}
// Match raw bean instance (might be raw FactoryBean).
// Step2.2:非FactoryBean並且匹配到了,則加入到結果集中
if (isTypeMatch(beanName, type)) {
result.add(beanName);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Shouldn't happen - probably a result of circular reference resolution...
if (logger.isDebugEnabled()) {
logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);
}
}
}
// Step3:返回匹配到的結果集
return StringUtils.toStringArray(result);
}
5. 以上即爲源碼的分析,所以的工作就是將BeanPostProcessor
註冊到BeanFactory
裏面,然後在 bean 實例初始化前做一些工作(關於這個我們在介紹 bean 實例初始化的地方會介紹)。接下來,來看一個例子來理解一下整個過程。
// 使用方法比較簡單,我們創建一個MyBeanPostProcessor,其實現了BeanPostProcessor接口和Ordered的接口
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
/**
* @author zxz
* 自定義BeanPostProcessor
*/
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {
public int getOrder() {
// 這個返回值是用來對實現了Ordered接口的BeanPostProcessor進行排序的
return 0;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization,該方法是在Bean實例初始化前被調用,執行一些特殊的邏輯");
// 這裏寫自己要做的特殊邏輯
if (bean instanceof UserService) {
System.out.println("UserService instance bean before");
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessAfterInitialization,該方法實在Bean實例初始化後被調用,執行特殊的邏輯");
// 這裏寫自己要做的特殊邏輯
if (bean instanceof UserService) {
System.out.println("UserService instance bean after");
}
return bean;
}
}
// xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="UserServiceImpl"/>
<!-- 注入自定義的BeanPostProcessor -->
<bean id="myBeanPostProcessor" class="MyBeanPostProcessor"/>
</beans>
// 單測
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class JuniteTest {
@Test
public void testBeanPostProcessor() {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserService userService = context.getBean(UserService.class);
userService.save();
}
}
從輸出結果來看,首先調用了重寫的postProcessBeforeInitialization()
和postProcessAfterInitialization()
方法。然後在UserService
的save
方法。
6. 以上內容爲BeanPostProcessor
註冊的全流程。現在來回答一下上篇文章留下的問題,invokeBeanFactoryPostProcessors()
和 registerBeanPostProcessors()
區別?
invokeBeanFactoryPostProcessors()
:操作的對象是BeanDefinition
定義,在此階段我們隨意修改BeanDefinition
定義的屬性相關。BeanFactoryPostProcessor
只提供了一個方法:postProcessBeanFactory()
registerBeanPostProcessors()
:操作的對象是BeanDefinition
定義對應的 Bean 實例,BeanPostProcessor
提供了兩個方法:postProcessBeforeInitialization()
和postProcessAfterInitialization()
。
總結
registerBeanPostProcessors
方法主要功能是將所有實現了BeanPostProcessor
接口或者實現了MergedBeanDefinitionPostProcessor
接口的類對應的實例註冊到BeanFactory
中(注意是將 Bean 實例註冊到BeanFactory
裏面)。
在該方法內部將BeanPostProcessor
分爲四類,分別是實現了PriorityOrdered
接口的、實現了Ordered
接口的、內部的和普通的。按照優先級依次排序將這四類BeanPostProcessor
註冊到BeanFactory
裏面。
BeanPostProcessor
提供的兩個方法的調用時機是在 Bean 實例初始化前後的時候被調用。
下一篇我們就來介紹 Spring 最核心的一個方法:finishBeanFactoryInitialization()
,看看它是怎麼把BeanDefinition
定義轉化成對應的 Bean 實例的,敬請期待。
歡迎關注我,共同學習