相關文章
- Spring 整體架構
- 編譯Spring5.2.0源碼
- Spring-資源加載
- Spring 容器的初始化
- Spring-AliasRegistry
- Spring 獲取單例流程(一)
- Spring 獲取單例流程(二)
- Spring 獲取單例流程(三)
- Spring 循環依賴
- Spring FactoryBean 緩存
- Spring Aware 接口
- Spring beanPostProcessor
上一篇文章我們聊了下 Aware
接口、今天我們再來聊一下 BeanPostProcessor
吧
爲了各位客官老爺們看代碼方便、不貼代碼了、直接截圖
其實再 AbstractBeanFactory
中有一個 List
專門存放着所有的 BeanPostProcessor
private final List<BeanPostProcessor> beanPostProcessors;
我們先來一睹 BeanPostProcessor
的真容吧
就那麼兩個方法
我們寫個小例子玩玩唄
運行 demo
, 居然沒有打印出來
看來我們需要手動註冊一波
defaultListableBeanFactory.addBeanPostProcessor(new Student());
我擦、這波操作有點騷啊、還真別這麼寫正常編碼的時候。再次運行
Student:postProcessBeforeInitialization:student
Student:postProcessAfterInitialization:student
BeanFactory 就這麼弱雞嗎 ? 記得 ApplicationContext
是不用我們去註冊的
我們使用一下 ApplicationContext
吧那就
運行一波、但是我的填爲啥還是沒打印呢、我們看看發生了啥、
當創建好 bean
然後回調 BeanPostProcessor
的時候、我們發現、在 beanPostProcessors
中並沒有 Student
這個對象、也就是沒有加入註冊進去
但是我們在 ApplicationContext
初始化之後查看、發現它又在了、這、究竟是怎麼回事呢 ( 我怎麼這麼多屁話 )
我先把調用鏈給出來吧
ClassPathXmlApplicationContext構造函數-->refresh()-->registerBeanPostProcessors()
registerBeanPostProcessors
看其名就知道它是幹啥的了、
registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
代碼有點長、我們一點點分析
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
這個代碼就是先從已經註冊的 beanDefinition
中找到所有實現了 BeanPostProcessor
的 beanName
、然後反手就註冊一個叫做 BeanPostProcessorChecker
的 BeanPostProcessor
。這個類有什麼作用呢、下次一定跟大家一起學習一下、下次一定
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
然後就定義了四個局部變量存放 beanName
或者 BeanPostProcessor
對象
priorityOrderedPostProcessors
這個是存放即實現了BeanPostProcessor
又實現了PriorityOrdered
接口的internalPostProcessors
存放的實現了PriorityOrdered
和MergedBeanDefinitionPostProcessor
接口的(MergedBeanDefinitionPostProcessor
繼承BeanPostProcessor
),可以認爲internalPostProcessors
是priorityOrderedPostProcessors
的子集orderedPostProcessorNames
存放實現了Ordered
接口的nonOrderedPostProcessorNames
撿漏上面都不是的
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)) {
// 爲啥不在這裏調用 getBean 方法、而是在下面的 for 循環中再調用、
orderedPostProcessorNames.add(ppName);
}
else {
// 爲啥不在這裏調用 getBean 方法、而是在下面的 for 循環中再調用、
nonOrderedPostProcessorNames.add(ppName);
}
}
上面的代碼就是遍歷獲取到的實現了 BeanPostProcessor
接口的 beanName
、如果它也實現了 PriorityOrdered
接口的、那就調用 getBean 方法獲取其 bean、如果只是實現了 Ordered 接口或者都沒實現的話、那麼就直接加入到對應的 List 中。這裏留個問題,爲啥保存實現 PriorityOrdered 接口的就要保存其 bean、實現 Ordered 或者都沒實現的爲啥只是保存其 beanName 、在上面的 else if 和 else 裏面 getBean 一下不就得了 ?
// 先進行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 註冊
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
這裏就是對實現了 PriorityOrdered 接口的 先進行排序、優先級高的先註冊
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);
// Now, register all regular BeanPostProcessors.
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);
上面的這些代碼都是差不多了的、都是能排序的話就先排序、然後再註冊
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
後面又重新註冊 internalPostProcessors 裏面的 BeanPostProcessor ,這個是什麼操作呢,我們看看具體的註冊方法
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
// 先移除
this.beanPostProcessors.remove(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// 再增加
this.beanPostProcessors.add(beanPostProcessor);
這麼操作一波之後、原來註冊的 BeanPostProcessor 的位置就會被移動到 List 的尾部了
我們再回到我們上面的問題,我們的 Student 類明明實現了 BeanPostProcessor 接口,但是卻沒有被回調到
我們看看對應的代碼
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);
ClassPathXmlApplicationContext構造函數-->refresh()-->registerBeanPostProcessors()
當我們在 refresh 的時候、執行到 registerBeanPostProcessors , 我們發現整個 Spring 管理的 BeanDefinition 集合中、只有 Student 是實現了 BeanPostProcessor 接口的、然後我們通過 getBean 方法去獲取這個 bean , 注意這個時候 AbstractBeanFactory 中的 beanPostProcessors 除了 Spring 自己加入的一些 BeanPostProcessor 之外,Student 的對象不存在於此( Student 的對象還沒被 Spring 創建出來) , 然後就走 getBean 的流程,走到 doCreateBean、走到 initializeBean 然後回調 BeanPostProcessor ,但是這個時候 Student 對象還是不在 beanPostProcessors 集合中、所以就不會打印了。其實可以得出一個結論,實現了 BeanPostProcessor 的 bean 當自身被 Spring 創建的時候、它是不會被回調到的
而上面還留了一個問題
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
爲啥 orderedPostProcessorNames 和 nonOrderedPostProcessorNames 的集合存放的是一個 String , 而不是直接是 BeanPostProcessor ?主要是爲了在創建實現 Ordered 接口的類的時候、即實現了 PriorityOrdered 接口又實現了 BeanPostProcessor 接口的對象得到回調,同理當創建非 PriorityOrdered/Ordered 接口的 bean 時,實現了 PriorityOrdered/Ordered 的 BeanPostProcessor 也能得到回調。這也是一種優先級的關係