spring bean post processor

相關文章web

上一篇文章咱們聊了下 Aware 接口、今天咱們再來聊一下 BeanPostProcessor緩存

爲了各位客官老爺們看代碼方便、不貼代碼了、直接截圖架構

其實再 AbstractBeanFactory 中有一個 List 專門存放着全部的 BeanPostProcessorapp

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 中找到全部實現了 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 也能獲得回調。這也是一種優先級的關係

羣聊
羣聊
此次必定?
此次必定?
相關文章
相關標籤/搜索