相關文章web
上一篇文章咱們聊了下 Aware
接口、今天咱們再來聊一下 BeanPostProcessor
吧緩存
爲了各位客官老爺們看代碼方便、不貼代碼了、直接截圖架構
其實再 AbstractBeanFactory
中有一個 List
專門存放着全部的 BeanPostProcessor
app
private final List<BeanPostProcessor> beanPostProcessors;
複製代碼
咱們先來一睹 BeanPostProcessor
的真容吧編輯器
就那麼兩個方法函數
咱們寫個小例子玩玩唄post
運行 demo
, 竟然沒有打印出來學習
看來咱們須要手動註冊一波this
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 也能獲得回調。這也是一種優先級的關係