spring bean post processor

相關文章

上一篇文章我們聊了下 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中找到所有實現了 BeanPostProcessorbeanName、然後反手就註冊一個叫做 BeanPostProcessorCheckerBeanPostProcessor。這個類有什麼作用呢、下次一定跟大家一起學習一下、下次一定

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存放的實現了 PriorityOrderedMergedBeanDefinitionPostProcessor接口的( MergedBeanDefinitionPostProcessor繼承 BeanPostProcessor),可以認爲 internalPostProcessorspriorityOrderedPostProcessors的子集
  • 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 也能得到回調。這也是一種優先級的關係

羣聊

這次一定?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章