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的執(zhí)行時機是在Spring掃描完成后,Bean初始化前,當(dāng)我們實現(xiàn)BeanFactoryPostProcessor接口,可以在Bean的初始化之前對Bean進(jìn)行屬性的修改
@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);
}
}
輸出結(jié)果為:false
上面的例子我們將A的BeanDefinition的scope設(shè)置為原型,默認(rèn)沒有設(shè)置scope的情況下bean的scope都是單例,也就是說我們成功的修改了A對象的beanDefinition,能修改的屬性不止這一個,還有是否懶加載,初始化方法名稱,設(shè)置屬性等等
而它的子類BeanDefinitionRegistryPostProcessor可以對spring容器中的BeanDefinition進(jìn)行操作
不了解BeanDefinition的可以先簡單理解為包裝Java類的一個類,例如我們給類設(shè)置的是否單例,是否懶加載這些信息都需要存儲,而spring就創(chuàng)建一個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);
}
}
輸出結(jié)果:
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類什么都沒有加,結(jié)果應(yīng)該是A獲取到正常輸出,然后獲取B時報錯找不到,但是結(jié)果恰恰相反,因為我們在MyBeanDefinitionRegistryPostProcessor類中對Spring管理的Bean進(jìn)行了修改,新增了一個B的BeanDefinition,刪除了A的BeanDefinition,所以結(jié)果就如上面呈現(xiàn)的那樣
完成了上面的簡單使用案例接下來就開始看Spring的執(zhí)行原理是什么
源碼分析
首先第一步要知道什么時候執(zhí)行的上面的代碼,為了方便就不將查找過程粘貼出來了,可以在實現(xiàn)類中輸出句話,Debug看看是在那個方法中輸出的
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
進(jìn)入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);
........
}
}
進(jìn)入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<>();
這個也很好理解,存放已經(jīng)執(zhí)行完的BeanFactoryPostProcessor名字,防止重復(fù)執(zhí)行
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//存放直接實現(xiàn)BeanFactoryPostProcessor,處理過/找到的實現(xiàn)類
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//存放直接實現(xiàn)BeanDefinitionRegistryPostProcessor,處理過/找到的實現(xiàn)類
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類型,大部分情況都是,我們先默認(rèn)它一直為true
那么上面定義兩個集合用來存放已經(jīng)處理過的實現(xiàn)類
下面這個for循環(huán)只有通過api來設(shè)置的BeanFactoryPostProcessor才會有值,什么意思呢?看下面
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Myconfig.class); context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());

為什么沒有呢?因為我們的代碼運行順序的問題,來看上面的使用代碼,是先new AnnotationConfigApplicationContext(MyConfig.class)
而在它的構(gòu)造中就已經(jīng)調(diào)用refresh->invokeBeanFactoryPostProcessors->invokeBeanFactoryPostProcessors方法了
而我們debug時候還沒有走到context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());方法,所以為空
那怎么使用?我們仔細(xì)來看AnnotationConfigApplicationContext的構(gòu)造
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
里面就3個方法,調(diào)自己無參,register,refresh,而執(zhí)行invokeBeanFactoryPostProcessors在refresh方法中,也就是說我們可以在refresh方法前進(jìn)行注冊即可
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Myconfig.class);
context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
context.refresh();
這樣,我們就能在refresh方法前進(jìn)行手動調(diào)用api的方式添加

繼續(xù)往下
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
判斷是BeanDefinitionRegistryPostProcessor類型,如果是,則直接執(zhí)行.否則添加到集合,還記得這個集合嗎在最外層的if中
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//存放直接實現(xiàn)BeanFactoryPostProcessor,處理過/找到的實現(xiàn)類
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//存放直接實現(xiàn)BeanDefinitionRegistryPostProcessor,處理過/找到的實現(xiàn)類
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
......
}
如果不是則添加到regularPostProcessors集合,為什么這個類型不執(zhí)行因為和Spring的執(zhí)行順序有關(guān),等到最后在說
從List
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();
首先這個集合干啥的:用來存放當(dāng)前需要執(zhí)行的BeanDefinitionRegistryPostProcessor
存放需要執(zhí)行的BeanDefinitionRegistryPostProcessor的好理解,那什么叫做當(dāng)前的?? 提前說一下,這個集合是在下面復(fù)用的,當(dāng)前的就是當(dāng)前正在執(zhí)行的BeanDefinitionRegistryPostProcessor類型是一類的,先往下看,一會再解釋
首先它創(chuàng)建一個字符串?dāng)?shù)組來接收beanFactory.getBeanNamesForType的返回參數(shù),簡單說下這個方法的作用
從BeanDefinitionNames中尋找類型為傳入類型的BeanDefinition的名稱
調(diào)用鏈為:DefaultListableBeanFactory.getBeanNamesForType->DefaultListableBeanFactory.doGetBeanNamesForType,有興趣可以自己去看看
那我們debug來看看獲取到類型是BeanDefinitionRegistryPostProcessor的beanName都有誰

那么繼續(xù)向下
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) 檢查傳入的PostProcessorName的BenaDefinition是否符合PriorityOrdered.class,當(dāng)然該方法的作用不止于此,我們現(xiàn)在只分析有關(guān)的
PriorityOrdered是一個排序的接口,它的父類是Ordered,誰的值越小越先調(diào)用,先簡單了解下即可,不是本章重點
public interface PriorityOrdered extends Ordered {
}
public interface Ordered {
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
int getOrder();
}

留個疑問,這個BeanDefinition什么時候進(jìn)來的?先繼續(xù)看代碼整體返回true進(jìn)入判斷
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
主要重點在getBean方法,以后有機會在單獨寫篇getBean的,簡單理解為從Spring的容器中獲取類,如果不存在則從BeanDefinitionMap中找到對應(yīng)BeanDefinition,然后實例化返回
那么假設(shè)我們已經(jīng)獲取到了實例化后的java對象,它是誰呢?debug

請記住這個類 ConfigurationClassPostProcessor
之后將當(dāng)前類的名稱存放到已經(jīng)處理過的set中,在該方法的最上面
//儲存已經(jīng)完成處理的BeanFactoryPostProcessor名字 Set<String> processedBeans = new HashSet<>();
之后調(diào)用排序方法,然后把已經(jīng)處理過的BeanFactoryPostProcessor存放到List
//存放直接實現(xiàn)BeanDefinitionRegistryPostProcessor,處理過的實現(xiàn)類 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數(shù)量即可


關(guān)于Spring的掃描以后有機會寫一篇
然后清空當(dāng)前正在執(zhí)行的List集合,繼續(xù)向下
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//這里判斷如果在存儲已經(jīng)完成的集合中沒有找到當(dāng)前的BeanDefinitionRegistryPostProcessor
//也就是說明這個還沒有被執(zhí)行過,那么放入當(dāng)前執(zhí)行的集合中進(jìn)行下一步操作
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);
//一樣的代碼,執(zhí)行postProcessBeanFactory方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
發(fā)現(xiàn)了什么,代碼和上面的很像,那么我們不在贅述,直接簡單說一下重點
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class))
判斷除了已經(jīng)處理過的,防止重復(fù)執(zhí)行,然后就是判斷類型,上面的類型是PriorityOrdered 現(xiàn)在是Ordered
那么再來看
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
而這個集合就是剛才定義的存放"當(dāng)前處理"的集合
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
什么叫當(dāng)前處理,在最開始執(zhí)行的時候,這個集合存放的都是實現(xiàn)PriorityOrdered接口的類,對于上面來說,"當(dāng)前處理的"就是實現(xiàn)PriotyOrdered類,然后代碼執(zhí)行到currentRegistryProcessors.clear();那么對于實現(xiàn)PriorityOrdered接口的類來說,"當(dāng)前處理"的這個集合,已經(jīng)不是存放PriorityOrdered接口的實現(xiàn)類了
而到了這里,這個list中只存放Ordered類型的,那么"當(dāng)前處理的"就指的是實現(xiàn)Ordered接口的類,因為它這個集合是好多地方復(fù)用的,所以叫做"當(dāng)前處理"集合
那么下面的代碼應(yīng)該能看明白吧,上面處理了實現(xiàn)PriorityOrdered,Ordered的BeanDefinitionRegistryPostProcessor,都執(zhí)行完了最后執(zhí)行沒有實現(xiàn)兩者的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);
這不是執(zhí)行過了嗎,為啥還要放集合,請注意,當(dāng)前找的接口是BeanDefinitionRegistryPostProcessor的實現(xiàn)類,而不是BeanFactoryPostProcessor,那么一個簡單的java基礎(chǔ)問題,一個類實現(xiàn)了A接口,而A接口又繼承B接口,請問這個類需要實現(xiàn)B接口定義的方法嗎,答案是肯定的,那么上面的只是執(zhí)行BeanDefinitionRegistryPostProcessor接口中定義的方法,所以來看后兩行就一目了然了
//為什么要傳入已經(jīng)執(zhí)行過的BeanDefinitionRegisterPostProcess的集合? //因為我們自定義的類實現(xiàn)了BeanDefinitionRegisterPostProcess這個接口 //而這個接口又繼承了BeanFactoryPostProcess,那么我們不僅要實現(xiàn)子類的方法,還要實現(xiàn)父類的方法 //而在上面的處理僅僅調(diào)用了子類的方法,所以又在這里調(diào)用一次父類的方法 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
好的,到此為止,使用Api添加的PostProcessor完成,但是有個小問題,發(fā)現(xiàn)了嗎,每次postProcessorNames都是重新獲取一次,為什么不獲取一次然后一直使用呢?
回過頭我們來看開始使用BeanDefinitionRegistryPostProcessor的簡單使用案例,假設(shè)實現(xiàn)PriorityOrdered接口的類在調(diào)用完postProcessBeanDefinitionRegistry方法對bean的數(shù)量進(jìn)行了修改,那么下面的操作獲取的數(shù)據(jù)都不是最新的,為了解決這個問題所以每次操作都重新獲取一遍
繼續(xù)向下走,下面的代碼就是我們通過掃描或xml找到的BeanFactoryPostProcessor實現(xiàn)類
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
//分別是存放實現(xiàn)了priorityOrdered接口,Ordered接口,和沒有實現(xiàn)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的實現(xiàn)類名稱,然后依次判斷實現(xiàn)了PriorityOrdered接口了嗎,實現(xiàn)Ordered接口了嗎,還是兩個都沒實現(xiàn)
分別放到對應(yīng)的集合中,隨后順序執(zhí)行
我們來捋一下執(zhí)行的順序
- 通過Api添加實現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
- Spring內(nèi)置實現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
- 掃描出的實現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
- 通過Api添加實現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法
- 執(zhí)行通過掃描/xml配置實現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法
- 執(zhí)行通過掃描/xml配置實現(xiàn)BeanFactoryPostProcessor接口的postProcessBeanFactory方法
如果有相同的類型,例如都是通過api添加實現(xiàn)BeanDefinitionRegistryPostProcessor接口的
那么執(zhí)行順序為先執(zhí)行實現(xiàn)PriorityOrdered接口,然后在執(zhí)行實現(xiàn)Ordered接口,最后在執(zhí)行兩個接口都沒實現(xiàn)的類
如果同一類型實現(xiàn)排序接口有多個,那么誰的實現(xiàn)方法返回值越小越先執(zhí)行
我們來寫代碼實際演示下
整體結(jié)構(gòu)如下

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掃描的方法中添加一句話用于輸出

排序的接口就不實現(xiàn)了,我們來看結(jié)果

也就是說如果想在Spring完成掃描前對Bean進(jìn)行一些操作可以實現(xiàn)BeanDefinitionRegistryPostProcessor接口并手動添加,而上面的輸出也顯示了,在同繼承PriorityOrdered或Ordered的時候,值小的先執(zhí)行
還有一個問題,我們在獲取BeanFactoryPostProcessor時名稱使用前每次都是重新獲取一下,而在下面通過掃描或Xml配置的BeanFactoryPostProcessor時卻只進(jìn)行一次獲取
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
因為BeanFactoryPostProcessor接口只是對bean進(jìn)行增強處理,不會進(jìn)行刪除新增的操作
回答上面的疑問:這個ConfigurationClassPostProcessor的BeanDefinition什么時候進(jìn)來的
來看new AnnotationConfigApplicationContext()的無參構(gòu)造
public AnnotationConfigApplicationContext() {
//spring內(nèi)置的bd將在這里進(jìn)行注冊
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);
}
也就是說在初始化時,如果不存在則進(jìn)行注冊beanDefinition,具體注冊的方法從
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
registry.registerBeanDefinition(beanName, definition);
DefaultListableBeanFactory.registerBeanDefinition注冊beanDefinition的方法,有興趣可以點進(jìn)去看看
到此這篇關(guān)于Spring源碼BeanFactoryPostProcessor詳解的文章就介紹到這了,更多相關(guān)Spring源碼BeanFactoryPostProcessor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot添加多數(shù)據(jù)源的方法實例教程
這篇文章主要給大家介紹了關(guān)于springboot添加多數(shù)據(jù)源方法的相關(guān)資料,在實際開發(fā)中經(jīng)??赡苡龅皆谝粋€應(yīng)用中可能要訪問多個數(shù)據(jù)庫多的情況,需要的朋友可以參考下2023-09-09
詳解如何使用Spring的@FeignClient注解實現(xiàn)通信功能
SpringBoot是一個非常流行的Java框架,它提供了一系列工具來使這種交互無縫且高效,在這些工具中,@FeignClient注解因其易用性和強大的功能而脫穎而出, 在這篇文章中,我們將探討如何使用Spring的@FeignClient注解進(jìn)行客戶端-服務(wù)器通信,需要的朋友可以參考下2023-11-11

