Spring源碼BeanFactoryPostProcessor詳解
Spring源碼分析-BeanFactoryPostProcessor
BeanFactoryPostProcessor接口是Spring提供的對Bean的擴展點,它的子接口是BeanDefinitionRegistryPostProcessor
@FunctionalInterface public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; } public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException; }
BeanFactoryPostProcessor簡單使用
BeanFactoryPostProcessor的執行時機是在Spring掃描完成後,Bean初始化前,當我們實現BeanFactoryPostProcessor接口,可以在Bean的初始化之前對Bean進行屬性的修改
@Component public class A { } @Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { BeanDefinition beanDefinition = beanFactory.getBeanDefinition("a"); beanDefinition.setScope("prototype"); } } @Configuration @ComponentScan("com.jame") public class Myconfig { } public class MyTest { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Myconfig.class); A a = context.getBean(A.class); A a1 = context.getBean(A.class); System.out.println(a==a1); } }
輸出結果為:false
上面的例子我們將A的BeanDefinition的scope設置為原型,默認沒有設置scope的情況下bean的scope都是單例,也就是說我們成功的修改瞭A對象的beanDefinition,能修改的屬性不止這一個,還有是否懶加載,初始化方法名稱,設置屬性等等
而它的子類BeanDefinitionRegistryPostProcessor可以對spring容器中的BeanDefinition進行操作
不瞭解BeanDefinition的可以先簡單理解為包裝Java類的一個類,例如我們給類設置的是否單例,是否懶加載這些信息都需要存儲,而spring就創建一個BeanDefinition,用來存儲除瞭java類以外的其他信息
BeanDefinitionRegistryPostProcessor簡單使用
@Component public class A { } public class B { } @Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { RootBeanDefinition beanDefinition = new RootBeanDefinition(B.class); registry.registerBeanDefinition("b",beanDefinition); registry.removeBeanDefinition("a"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } } @Configuration @ComponentScan("com.jame") public class Myconfig { } public class MyTest { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Myconfig.class); B b = context.getBean(B.class); System.out.println(b); A a = context.getBean(A.class); } }
輸出結果:
com.jame.pojo.B@2ac1fdc4
Exception in thread “main” org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘com.jame.pojo.A’ available……
上面的代碼中我們對A類加上瞭@Component,B類什麼都沒有加,結果應該是A獲取到正常輸出,然後獲取B時報錯找不到,但是結果恰恰相反,因為我們在MyBeanDefinitionRegistryPostProcessor類中對Spring管理的Bean進行瞭修改,新增瞭一個B的BeanDefinition,刪除瞭A的BeanDefinition,所以結果就如上面呈現的那樣
完成瞭上面的簡單使用案例接下來就開始看Spring的執行原理是什麼
源碼分析
首先第一步要知道什麼時候執行的上面的代碼,為瞭方便就不將查找過程粘貼出來瞭,可以在實現類中輸出句話,Debug看看是在那個方法中輸出的
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); register(componentClasses); refresh(); }
進入refresh方法
@Override public void refresh() throws BeansException, IllegalStateException { ...... try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); ........ } }
進入invokeBeanFactoryPostProcessors方法
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); beanFactory.clearMetadataCache(); }
來看最上面定義
Set<String> processedBeans = new HashSet<>();
這個也很好理解,存放已經執行完的BeanFactoryPostProcessor名字,防止重復執行
if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; //存放直接實現BeanFactoryPostProcessor,處理過/找到的實現類 List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); //存放直接實現BeanDefinitionRegistryPostProcessor,處理過/找到的實現類 List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } }
來看第一個if判斷,判斷傳入的BeanFactory是否是BeanDefinitionRegistry類型,大部分情況都是,我們先默認它一直為true
那麼上面定義兩個集合用來存放已經處理過的實現類
下面這個for循環隻有通過api來設置的BeanFactoryPostProcessor才會有值,什麼意思呢?看下面
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Myconfig.class); context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
為什麼沒有呢?因為我們的代碼運行順序的問題,來看上面的使用代碼,是先new AnnotationConfigApplicationContext(MyConfig.class)
而在它的構造中就已經調用refresh->invokeBeanFactoryPostProcessors->invokeBeanFactoryPostProcessors方法瞭
而我們debug時候還沒有走到context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
方法,所以為空
那怎麼使用?我們仔細來看AnnotationConfigApplicationContext
的構造
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); register(componentClasses); refresh(); }
裡面就3個方法,調自己無參,register,refresh,而執行invokeBeanFactoryPostProcessors在refresh方法中,也就是說我們可以在refresh方法前進行註冊即可
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Myconfig.class); context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor()); context.refresh();
這樣,我們就能在refresh方法前進行手動調用api的方式添加
繼續往下
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); }
判斷是BeanDefinitionRegistryPostProcessor類型,如果是,則直接執行.否則添加到集合,還記得這個集合嗎在最外層的if中
if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; //存放直接實現BeanFactoryPostProcessor,處理過/找到的實現類 List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); //存放直接實現BeanDefinitionRegistryPostProcessor,處理過/找到的實現類 List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); ...... }
如果不是則添加到regularPostProcessors集合,為什麼這個類型不執行因為和Spring的執行順序有關,等到最後在說
從List currentRegistryProcessors = new ArrayList<>();創建這個集合開始向下看
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();
首先這個集合幹啥的:用來存放當前需要執行的BeanDefinitionRegistryPostProcessor
存放需要執行的BeanDefinitionRegistryPostProcessor的好理解,那什麼叫做當前的?? 提前說一下,這個集合是在下面復用的,當前的就是當前正在執行的BeanDefinitionRegistryPostProcessor類型是一類的,先往下看,一會再解釋
首先它創建一個字符串數組來接收beanFactory.getBeanNamesForType的返回參數,簡單說下這個方法的作用
從BeanDefinitionNames中尋找類型為傳入類型的BeanDefinition的名稱
調用鏈為:DefaultListableBeanFactory.getBeanNamesForType->DefaultListableBeanFactory.doGetBeanNamesForType,有興趣可以自己去看看
那我們debug來看看獲取到類型是BeanDefinitionRegistryPostProcessor的beanName都有誰
那麼繼續向下
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) 檢查傳入的PostProcessorName的BenaDefinition是否符合PriorityOrdered.class,當然該方法的作用不止於此,我們現在隻分析有關的
PriorityOrdered是一個排序的接口,它的父類是Ordered,誰的值越小越先調用,先簡單瞭解下即可,不是本章重點
public interface PriorityOrdered extends Ordered { } public interface Ordered { int HIGHEST_PRECEDENCE = Integer.MIN_VALUE; int LOWEST_PRECEDENCE = Integer.MAX_VALUE; int getOrder(); }
留個疑問,這個BeanDefinition什麼時候進來的?先繼續看代碼整體返回true進入判斷
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
主要重點在getBean方法,以後有機會在單獨寫篇getBean的,簡單理解為從Spring的容器中獲取類,如果不存在則從BeanDefinitionMap中找到對應BeanDefinition,然後實例化返回
那麼假設我們已經獲取到瞭實例化後的java對象,它是誰呢?debug
請記住這個類 ConfigurationClassPostProcessor
之後將當前類的名稱存放到已經處理過的set中,在該方法的最上面
//儲存已經完成處理的BeanFactoryPostProcessor名字 Set<String> processedBeans = new HashSet<>();
之後調用排序方法,然後把已經處理過的BeanFactoryPostProcessor存放到List
//存放直接實現BeanDefinitionRegistryPostProcessor,處理過的實現類 List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
我們重點來看invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
方法
private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } }
上面找到的ConfigurationClassPostProcessor是重中之重,Spring的掃描就是這個類中完成的,何以證明?Debug
我們來看beanFactory中的BeanDefinitionMap數量即可
關於Spring的掃描以後有機會寫一篇
然後清空當前正在執行的List集合,繼續向下
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { //這裡判斷如果在存儲已經完成的集合中沒有找到當前的BeanDefinitionRegistryPostProcessor //也就是說明這個還沒有被執行過,那麼放入當前執行的集合中進行下一步操作 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); //一樣的代碼,執行postProcessBeanFactory方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();
發現瞭什麼,代碼和上面的很像,那麼我們不在贅述,直接簡單說一下重點
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class))
判斷除瞭已經處理過的,防止重復執行,然後就是判斷類型,上面的類型是PriorityOrdered
現在是Ordered
那麼再來看
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
而這個集合就是剛才定義的存放”當前處理”的集合
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
什麼叫當前處理,在最開始執行的時候,這個集合存放的都是實現PriorityOrdered接口的類,對於上面來說,”當前處理的”就是實現PriotyOrdered類,然後代碼執行到currentRegistryProcessors.clear();那麼對於實現PriorityOrdered接口的類來說,”當前處理”的這個集合,已經不是存放PriorityOrdered接口的實現類瞭
而到瞭這裡,這個list中隻存放Ordered類型的,那麼”當前處理的”就指的是實現Ordered接口的類,因為它這個集合是好多地方復用的,所以叫做”當前處理”集合
那麼下面的代碼應該能看明白吧,上面處理瞭實現PriorityOrdered,Ordered的BeanDefinitionRegistryPostProcessor,都執行完瞭最後執行沒有實現兩者的BeanDefinitionRegistryPostProcessor
boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); }
那麼這裡可能有個疑問
registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
這不是執行過瞭嗎,為啥還要放集合,請註意,當前找的接口是BeanDefinitionRegistryPostProcessor的實現類,而不是BeanFactoryPostProcessor,那麼一個簡單的java基礎問題,一個類實現瞭A接口,而A接口又繼承B接口,請問這個類需要實現B接口定義的方法嗎,答案是肯定的,那麼上面的隻是執行BeanDefinitionRegistryPostProcessor接口中定義的方法,所以來看後兩行就一目瞭然瞭
//為什麼要傳入已經執行過的BeanDefinitionRegisterPostProcess的集合? //因為我們自定義的類實現瞭BeanDefinitionRegisterPostProcess這個接口 //而這個接口又繼承瞭BeanFactoryPostProcess,那麼我們不僅要實現子類的方法,還要實現父類的方法 //而在上面的處理僅僅調用瞭子類的方法,所以又在這裡調用一次父類的方法 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
好的,到此為止,使用Api添加的PostProcessor完成,但是有個小問題,發現瞭嗎,每次postProcessorNames都是重新獲取一次,為什麼不獲取一次然後一直使用呢?
回過頭我們來看開始使用BeanDefinitionRegistryPostProcessor的簡單使用案例,假設實現PriorityOrdered接口的類在調用完postProcessBeanDefinitionRegistry方法對bean的數量進行瞭修改,那麼下面的操作獲取的數據都不是最新的,為瞭解決這個問題所以每次操作都重新獲取一遍
繼續向下走,下面的代碼就是我們通過掃描或xml找到的BeanFactoryPostProcessor實現類
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. //分別是存放實現瞭priorityOrdered接口,Ordered接口,和沒有實現Ordered接口的名稱集合 List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
下面的代碼就比較簡單瞭,就簡單寫下
首先還是通過 beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
獲取類型為BeanFactoryPostProcessor的實現類名稱,然後依次判斷實現瞭PriorityOrdered接口瞭嗎,實現Ordered接口瞭嗎,還是兩個都沒實現
分別放到對應的集合中,隨後順序執行
我們來捋一下執行的順序
- 通過Api添加實現BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
- Spring內置實現BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
- 掃描出的實現BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
- 通過Api添加實現BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法
- 執行通過掃描/xml配置實現BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法
- 執行通過掃描/xml配置實現BeanFactoryPostProcessor接口的postProcessBeanFactory方法
如果有相同的類型,例如都是通過api添加實現BeanDefinitionRegistryPostProcessor接口的
那麼執行順序為先執行實現PriorityOrdered接口,然後在執行實現Ordered接口,最後在執行兩個接口都沒實現的類
如果同一類型實現排序接口有多個,那麼誰的實現方法返回值越小越先執行
我們來寫代碼實際演示下
整體結構如下
public class BDRPP_API implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println("API-BDRPP_API的postProcessBeanDefinitionRegistry方法"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("API-BDRPP_API的postProcessBeanFactory方法"); } } @Component public class BDRPP_Scan implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println("掃描-BDRPP_Scan的postProcessBeanDefinitionRegistry方法"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("掃描-BDRPP_Scan的postProcessBeanFactory方法"); } } @Component public class BFPP_Scan implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("掃描-BFPP_Scan類的postProcessBeanFactory方法"); } }
在Spring掃描的方法中添加一句話用於輸出
排序的接口就不實現瞭,我們來看結果
也就是說如果想在Spring完成掃描前對Bean進行一些操作可以實現BeanDefinitionRegistryPostProcessor接口並手動添加,而上面的輸出也顯示瞭,在同繼承PriorityOrdered或Ordered的時候,值小的先執行
還有一個問題,我們在獲取BeanFactoryPostProcessor時名稱使用前每次都是重新獲取一下,而在下面通過掃描或Xml配置的BeanFactoryPostProcessor時卻隻進行一次獲取
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
因為BeanFactoryPostProcessor接口隻是對bean進行增強處理,不會進行刪除新增的操作
回答上面的疑問:這個ConfigurationClassPostProcessor的BeanDefinition什麼時候進來的
來看new AnnotationConfigApplicationContext()的無參構造
public AnnotationConfigApplicationContext() { //spring內置的bd將在這裡進行註冊 this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); //這裡 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { ..... if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } ....... }
還記得上面第一次通過String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
來看CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME這個常量的值是啥
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
而它這個if判斷是
@Override public boolean containsBeanDefinition(String beanName) { Assert.notNull(beanName, "Bean name must not be null"); return this.beanDefinitionMap.containsKey(beanName); }
也就是說在初始化時,如果不存在則進行註冊beanDefinition,具體註冊的方法從
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
registry.registerBeanDefinition(beanName, definition);
DefaultListableBeanFactory.registerBeanDefinition註冊beanDefinition的方法,有興趣可以點進去看看
到此這篇關於Spring源碼BeanFactoryPostProcessor詳解的文章就介紹到這瞭,更多相關Spring源碼BeanFactoryPostProcessor內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Spring的BeanFactoryPostProcessor接口示例代碼詳解
- Java 圖解Spring啟動時的後置處理器工作流程是怎樣的
- Java 確保某個Bean類被最後執行的幾種實現方式
- Spring源碼解析之Configuration
- 詳解Spring ApplicationContext加載過程