欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring源碼BeanFactoryPostProcessor詳解

 更新時(shí)間:2021年11月17日 14:41:15   作者:Jame!  
BeanFactoryPostProcessor的執(zhí)行時(shí)機(jī)是在Spring掃描完成后,Bean初始化前,當(dāng)我們實(shí)現(xiàn)BeanFactoryPostProcessor接口,可以在Bean的初始化之前對(duì)Bean進(jìn)行屬性的修改,下面通過(guò)本文看下Spring源碼分析-BeanFactoryPostProcessor的實(shí)例代碼,感興趣的朋友一起看看吧

Spring源碼分析-BeanFactoryPostProcessor

BeanFactoryPostProcessor接口是Spring提供的對(duì)Bean的擴(kuò)展點(diǎn),它的子接口是BeanDefinitionRegistryPostProcessor

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

BeanFactoryPostProcessor簡(jiǎn)單使用

BeanFactoryPostProcessor的執(zhí)行時(shí)機(jī)是在Spring掃描完成后,Bean初始化前,當(dāng)我們實(shí)現(xiàn)BeanFactoryPostProcessor接口,可以在Bean的初始化之前對(duì)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)沒(méi)有設(shè)置scope的情況下bean的scope都是單例,也就是說(shuō)我們成功的修改了A對(duì)象的beanDefinition,能修改的屬性不止這一個(gè),還有是否懶加載,初始化方法名稱,設(shè)置屬性等等

而它的子類BeanDefinitionRegistryPostProcessor可以對(duì)spring容器中的BeanDefinition進(jìn)行操作

不了解BeanDefinition的可以先簡(jiǎn)單理解為包裝Java類的一個(gè)類,例如我們給類設(shè)置的是否單例,是否懶加載這些信息都需要存儲(chǔ),而spring就創(chuàng)建一個(gè)BeanDefinition,用來(lái)存儲(chǔ)除了java類以外的其他信息

BeanDefinitionRegistryPostProcessor簡(jiǎn)單使用

@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......

上面的代碼中我們對(duì)A類加上了@Component,B類什么都沒(méi)有加,結(jié)果應(yīng)該是A獲取到正常輸出,然后獲取B時(shí)報(bào)錯(cuò)找不到,但是結(jié)果恰恰相反,因?yàn)槲覀冊(cè)贛yBeanDefinitionRegistryPostProcessor類中對(duì)Spring管理的Bean進(jìn)行了修改,新增了一個(gè)B的BeanDefinition,刪除了A的BeanDefinition,所以結(jié)果就如上面呈現(xiàn)的那樣

完成了上面的簡(jiǎn)單使用案例接下來(lái)就開(kāi)始看Spring的執(zhí)行原理是什么

源碼分析

首先第一步要知道什么時(shí)候執(zhí)行的上面的代碼,為了方便就不將查找過(guò)程粘貼出來(lái)了,可以在實(shí)現(xiàn)類中輸出句話,Debug看看是在那個(gè)方法中輸出的

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();
	}

來(lái)看最上面定義

Set<String> processedBeans = new HashSet<>();

這個(gè)也很好理解,存放已經(jīng)執(zhí)行完的BeanFactoryPostProcessor名字,防止重復(fù)執(zhí)行

if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

			//存放直接實(shí)現(xiàn)BeanFactoryPostProcessor,處理過(guò)/找到的實(shí)現(xiàn)類
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();

			//存放直接實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor,處理過(guò)/找到的實(shí)現(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);
				}
			}

來(lái)看第一個(gè)if判斷,判斷傳入的BeanFactory是否是BeanDefinitionRegistry類型,大部分情況都是,我們先默認(rèn)它一直為true

那么上面定義兩個(gè)集合用來(lái)存放已經(jīng)處理過(guò)的實(shí)現(xiàn)類

下面這個(gè)for循環(huán)只有通過(guò)api來(lái)設(shè)置的BeanFactoryPostProcessor才會(huì)有值,什么意思呢?看下面

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Myconfig.class);
context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());

為什么沒(méi)有呢?因?yàn)槲覀兊拇a運(yùn)行順序的問(wèn)題,來(lái)看上面的使用代碼,是先new AnnotationConfigApplicationContext(MyConfig.class)

而在它的構(gòu)造中就已經(jīng)調(diào)用refresh->invokeBeanFactoryPostProcessors->invokeBeanFactoryPostProcessors方法了

而我們debug時(shí)候還沒(méi)有走到context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());方法,所以為空

那怎么使用?我們仔細(xì)來(lái)看AnnotationConfigApplicationContext的構(gòu)造

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();   
    register(componentClasses);    
    refresh();
}

里面就3個(gè)方法,調(diào)自己無(wú)參,register,refresh,而執(zhí)行invokeBeanFactoryPostProcessors在refresh方法中,也就是說(shuō)我們可以在refresh方法前進(jìn)行注冊(cè)即可

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(Myconfig.class);
    context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
    context.refresh();

這樣,我們就能在refresh方法前進(jìn)行手動(dòng)調(diào)用api的方式添加

繼續(xù)往下

if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
    BeanDefinitionRegistryPostProcessor registryProcessor =
        (BeanDefinitionRegistryPostProcessor) postProcessor;
    registryProcessor.postProcessBeanDefinitionRegistry(registry);
    registryProcessors.add(registryProcessor);
} else {
    regularPostProcessors.add(postProcessor);
}

判斷是BeanDefinitionRegistryPostProcessor類型,如果是,則直接執(zhí)行.否則添加到集合,還記得這個(gè)集合嗎在最外層的if中

if (beanFactory instanceof BeanDefinitionRegistry) {
    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

    //存放直接實(shí)現(xiàn)BeanFactoryPostProcessor,處理過(guò)/找到的實(shí)現(xiàn)類
    List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();

    //存放直接實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor,處理過(guò)/找到的實(shí)現(xiàn)類
    List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    ......
}

如果不是則添加到regularPostProcessors集合,為什么這個(gè)類型不執(zhí)行因?yàn)楹蚐pring的執(zhí)行順序有關(guān),等到最后在說(shuō)

從List currentRegistryProcessors = new ArrayList<>();創(chuàng)建這個(gè)集合開(kāi)始向下看

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();

首先這個(gè)集合干啥的:用來(lái)存放當(dāng)前需要執(zhí)行的BeanDefinitionRegistryPostProcessor

存放需要執(zhí)行的BeanDefinitionRegistryPostProcessor的好理解,那什么叫做當(dāng)前的?? 提前說(shuō)一下,這個(gè)集合是在下面復(fù)用的,當(dāng)前的就是當(dāng)前正在執(zhí)行的BeanDefinitionRegistryPostProcessor類型是一類的,先往下看,一會(huì)再解釋

首先它創(chuàng)建一個(gè)字符串?dāng)?shù)組來(lái)接收beanFactory.getBeanNamesForType的返回參數(shù),簡(jiǎn)單說(shuō)下這個(gè)方法的作用

從BeanDefinitionNames中尋找類型為傳入類型的BeanDefinition的名稱

調(diào)用鏈為:DefaultListableBeanFactory.getBeanNamesForType->DefaultListableBeanFactory.doGetBeanNamesForType,有興趣可以自己去看看

那我們debug來(lái)看看獲取到類型是BeanDefinitionRegistryPostProcessor的beanName都有誰(shuí)

那么繼續(xù)向下

if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) 檢查傳入的PostProcessorName的BenaDefinition是否符合PriorityOrdered.class,當(dāng)然該方法的作用不止于此,我們現(xiàn)在只分析有關(guān)的

PriorityOrdered是一個(gè)排序的接口,它的父類是Ordered,誰(shuí)的值越小越先調(diào)用,先簡(jiǎn)單了解下即可,不是本章重點(diǎn)

public interface PriorityOrdered extends Ordered {
}

public interface Ordered {
	int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
	int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
	int getOrder();
}

留個(gè)疑問(wèn),這個(gè)BeanDefinition什么時(shí)候進(jìn)來(lái)的?先繼續(xù)看代碼整體返回true進(jìn)入判斷

currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

主要重點(diǎn)在getBean方法,以后有機(jī)會(huì)在單獨(dú)寫篇getBean的,簡(jiǎn)單理解為從Spring的容器中獲取類,如果不存在則從BeanDefinitionMap中找到對(duì)應(yīng)BeanDefinition,然后實(shí)例化返回

那么假設(shè)我們已經(jīng)獲取到了實(shí)例化后的java對(duì)象,它是誰(shuí)呢?debug

請(qǐng)記住這個(gè)類 ConfigurationClassPostProcessor

之后將當(dāng)前類的名稱存放到已經(jīng)處理過(guò)的set中,在該方法的最上面

//儲(chǔ)存已經(jīng)完成處理的BeanFactoryPostProcessor名字
Set<String> processedBeans = new HashSet<>();

之后調(diào)用排序方法,然后把已經(jīng)處理過(guò)的BeanFactoryPostProcessor存放到List

//存放直接實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor,處理過(guò)的實(shí)現(xiàn)類
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

我們重點(diǎn)來(lái)看invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);方法

private static void invokeBeanDefinitionRegistryPostProcessors(
    Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

上面找到的ConfigurationClassPostProcessor是重中之重,Spring的掃描就是這個(gè)類中完成的,何以證明?Debug

我們來(lái)看beanFactory中的BeanDefinitionMap數(shù)量即可

關(guān)于Spring的掃描以后有機(jī)會(huì)寫一篇

然后清空當(dāng)前正在執(zhí)行的List集合,繼續(xù)向下

postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
    //這里判斷如果在存儲(chǔ)已經(jīng)完成的集合中沒(méi)有找到當(dāng)前的BeanDefinitionRegistryPostProcessor
    //也就是說(shuō)明這個(gè)還沒(méi)有被執(zhí)行過(guò),那么放入當(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)了什么,代碼和上面的很像,那么我們不在贅述,直接簡(jiǎn)單說(shuō)一下重點(diǎn)

if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) 

判斷除了已經(jīng)處理過(guò)的,防止重復(fù)執(zhí)行,然后就是判斷類型,上面的類型是PriorityOrdered 現(xiàn)在是Ordered

那么再來(lái)看

 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

而這個(gè)集合就是剛才定義的存放"當(dāng)前處理"的集合

List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

什么叫當(dāng)前處理,在最開(kāi)始執(zhí)行的時(shí)候,這個(gè)集合存放的都是實(shí)現(xiàn)PriorityOrdered接口的類,對(duì)于上面來(lái)說(shuō),"當(dāng)前處理的"就是實(shí)現(xiàn)PriotyOrdered類,然后代碼執(zhí)行到currentRegistryProcessors.clear();那么對(duì)于實(shí)現(xiàn)PriorityOrdered接口的類來(lái)說(shuō),"當(dāng)前處理"的這個(gè)集合,已經(jīng)不是存放PriorityOrdered接口的實(shí)現(xiàn)類了

而到了這里,這個(gè)list中只存放Ordered類型的,那么"當(dāng)前處理的"就指的是實(shí)現(xiàn)Ordered接口的類,因?yàn)樗@個(gè)集合是好多地方復(fù)用的,所以叫做"當(dāng)前處理"集合

那么下面的代碼應(yīng)該能看明白吧,上面處理了實(shí)現(xiàn)PriorityOrdered,Ordered的BeanDefinitionRegistryPostProcessor,都執(zhí)行完了最后執(zhí)行沒(méi)有實(shí)現(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();
}

那么這里可能有個(gè)疑問(wèn)

registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

這不是執(zhí)行過(guò)了嗎,為啥還要放集合,請(qǐng)注意,當(dāng)前找的接口是BeanDefinitionRegistryPostProcessor的實(shí)現(xiàn)類,而不是BeanFactoryPostProcessor,那么一個(gè)簡(jiǎn)單的java基礎(chǔ)問(wèn)題,一個(gè)類實(shí)現(xiàn)了A接口,而A接口又繼承B接口,請(qǐng)問(wèn)這個(gè)類需要實(shí)現(xiàn)B接口定義的方法嗎,答案是肯定的,那么上面的只是執(zhí)行BeanDefinitionRegistryPostProcessor接口中定義的方法,所以來(lái)看后兩行就一目了然了

//為什么要傳入已經(jīng)執(zhí)行過(guò)的BeanDefinitionRegisterPostProcess的集合?
//因?yàn)槲覀冏远x的類實(shí)現(xiàn)了BeanDefinitionRegisterPostProcess這個(gè)接口
//而這個(gè)接口又繼承了BeanFactoryPostProcess,那么我們不僅要實(shí)現(xiàn)子類的方法,還要實(shí)現(xiàn)父類的方法
//而在上面的處理僅僅調(diào)用了子類的方法,所以又在這里調(diào)用一次父類的方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

好的,到此為止,使用Api添加的PostProcessor完成,但是有個(gè)小問(wèn)題,發(fā)現(xiàn)了嗎,每次postProcessorNames都是重新獲取一次,為什么不獲取一次然后一直使用呢?

回過(guò)頭我們來(lái)看開(kāi)始使用BeanDefinitionRegistryPostProcessor的簡(jiǎn)單使用案例,假設(shè)實(shí)現(xiàn)PriorityOrdered接口的類在調(diào)用完postProcessBeanDefinitionRegistry方法對(duì)bean的數(shù)量進(jìn)行了修改,那么下面的操作獲取的數(shù)據(jù)都不是最新的,為了解決這個(gè)問(wèn)題所以每次操作都重新獲取一遍

繼續(xù)向下走,下面的代碼就是我們通過(guò)掃描或xml找到的BeanFactoryPostProcessor實(shí)現(xiàn)類

String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
//分別是存放實(shí)現(xiàn)了priorityOrdered接口,Ordered接口,和沒(méi)有實(shí)現(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);



下面的代碼就比較簡(jiǎn)單了,就簡(jiǎn)單寫下

首先還是通過(guò) beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);獲取類型為BeanFactoryPostProcessor的實(shí)現(xiàn)類名稱,然后依次判斷實(shí)現(xiàn)了PriorityOrdered接口了嗎,實(shí)現(xiàn)Ordered接口了嗎,還是兩個(gè)都沒(méi)實(shí)現(xiàn)

分別放到對(duì)應(yīng)的集合中,隨后順序執(zhí)行

我們來(lái)捋一下執(zhí)行的順序

  1. 通過(guò)Api添加實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
  2. Spring內(nèi)置實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
  3. 掃描出的實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
  4. 通過(guò)Api添加實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法
  5. 執(zhí)行通過(guò)掃描/xml配置實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法
  6. 執(zhí)行通過(guò)掃描/xml配置實(shí)現(xiàn)BeanFactoryPostProcessor接口的postProcessBeanFactory方法

如果有相同的類型,例如都是通過(guò)api添加實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的

那么執(zhí)行順序?yàn)橄葓?zhí)行實(shí)現(xiàn)PriorityOrdered接口,然后在執(zhí)行實(shí)現(xiàn)Ordered接口,最后在執(zhí)行兩個(gè)接口都沒(méi)實(shí)現(xiàn)的類

如果同一類型實(shí)現(xiàn)排序接口有多個(gè),那么誰(shuí)的實(shí)現(xiàn)方法返回值越小越先執(zhí)行

我們來(lái)寫代碼實(shí)際演示下

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

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

也就是說(shuō)如果想在Spring完成掃描前對(duì)Bean進(jìn)行一些操作可以實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口并手動(dòng)添加,而上面的輸出也顯示了,在同繼承PriorityOrdered或Ordered的時(shí)候,值小的先執(zhí)行

還有一個(gè)問(wèn)題,我們?cè)讷@取BeanFactoryPostProcessor時(shí)名稱使用前每次都是重新獲取一下,而在下面通過(guò)掃描或Xml配置的BeanFactoryPostProcessor時(shí)卻只進(jìn)行一次獲取

String[] postProcessorNames =    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

因?yàn)锽eanFactoryPostProcessor接口只是對(duì)bean進(jìn)行增強(qiáng)處理,不會(huì)進(jìn)行刪除新增的操作

回答上面的疑問(wèn):這個(gè)ConfigurationClassPostProcessor的BeanDefinition什么時(shí)候進(jìn)來(lái)的

來(lái)看new AnnotationConfigApplicationContext()的無(wú)參構(gòu)造

public AnnotationConfigApplicationContext() {
    //spring內(nèi)置的bd將在這里進(jìn)行注冊(cè)
    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));
        }
    .......
}

還記得上面第一次通過(guò)String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

來(lái)看CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME這個(gè)常量的值是啥

public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
    "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";

而它這個(gè)if判斷是

@Override
public boolean containsBeanDefinition(String beanName) {
    Assert.notNull(beanName, "Bean name must not be null");
    return this.beanDefinitionMap.containsKey(beanName);
}

也就是說(shuō)在初始化時(shí),如果不存在則進(jìn)行注冊(cè)beanDefinition,具體注冊(cè)的方法從

beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

registry.registerBeanDefinition(beanName, definition);

DefaultListableBeanFactory.registerBeanDefinition注冊(cè)beanDefinition的方法,有興趣可以點(diǎn)進(jìn)去看看

到此這篇關(guān)于Spring源碼BeanFactoryPostProcessor詳解的文章就介紹到這了,更多相關(guān)Spring源碼BeanFactoryPostProcessor內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot配置攔截器的示例

    SpringBoot配置攔截器的示例

    這篇文章主要介紹了SpringBoot配置攔截器的示例,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下
    2020-11-11
  • springboot添加多數(shù)據(jù)源的方法實(shí)例教程

    springboot添加多數(shù)據(jù)源的方法實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于springboot添加多數(shù)據(jù)源方法的相關(guān)資料,在實(shí)際開(kāi)發(fā)中經(jīng)常可能遇到在一個(gè)應(yīng)用中可能要訪問(wèn)多個(gè)數(shù)據(jù)庫(kù)多的情況,需要的朋友可以參考下
    2023-09-09
  • 利用SpringBoot解決多個(gè)定時(shí)任務(wù)阻塞的問(wèn)題

    利用SpringBoot解決多個(gè)定時(shí)任務(wù)阻塞的問(wèn)題

    當(dāng)我們?cè)赟pring Boot應(yīng)用中使用多個(gè)定時(shí)任務(wù)時(shí),任務(wù)之間的阻塞可能是一個(gè)常見(jiàn)的問(wèn)題,這可能會(huì)因任務(wù)之間的依賴、執(zhí)行時(shí)間過(guò)長(zhǎng)或資源爭(zhēng)用等原因而發(fā)生,本文讓我們深入探討如何利用Spring Boot來(lái)解決多個(gè)定時(shí)任務(wù)阻塞的問(wèn)題,感興趣的小伙伴跟著小編一起來(lái)看看吧
    2024-01-01
  • Java實(shí)現(xiàn)身份證號(hào)碼驗(yàn)證源碼示例分享

    Java實(shí)現(xiàn)身份證號(hào)碼驗(yàn)證源碼示例分享

    本篇文章主要介紹了Java實(shí)現(xiàn)身份證號(hào)碼驗(yàn)證源碼示例分享,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • 詳解如何使用Spring的@FeignClient注解實(shí)現(xiàn)通信功能

    詳解如何使用Spring的@FeignClient注解實(shí)現(xiàn)通信功能

    SpringBoot是一個(gè)非常流行的Java框架,它提供了一系列工具來(lái)使這種交互無(wú)縫且高效,在這些工具中,@FeignClient注解因其易用性和強(qiáng)大的功能而脫穎而出, 在這篇文章中,我們將探討如何使用Spring的@FeignClient注解進(jìn)行客戶端-服務(wù)器通信,需要的朋友可以參考下
    2023-11-11
  • Java編程枚舉類實(shí)戰(zhàn)代碼分享

    Java編程枚舉類實(shí)戰(zhàn)代碼分享

    這篇文章主要介紹了Java編程枚舉類實(shí)戰(zhàn)代碼分享,具有一定借鑒價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Proxy實(shí)現(xiàn)AOP切面編程案例

    Proxy實(shí)現(xiàn)AOP切面編程案例

    這篇文章主要介紹了Proxy實(shí)現(xiàn)AOP切面編程案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • Java8如何使用Lambda表達(dá)式簡(jiǎn)化代碼詳解

    Java8如何使用Lambda表達(dá)式簡(jiǎn)化代碼詳解

    這篇文章主要給大家介紹了關(guān)于Java8如何使用Lambda表達(dá)式簡(jiǎn)化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Springboot如何通過(guò)自定義工具類獲取bean

    Springboot如何通過(guò)自定義工具類獲取bean

    這篇文章主要介紹了Springboot通過(guò)自定義工具類獲取bean方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 淺談對(duì)于DAO設(shè)計(jì)模式的理解

    淺談對(duì)于DAO設(shè)計(jì)模式的理解

    這篇文章主要介紹了淺談對(duì)于DAO設(shè)計(jì)模式的理解,小編覺(jué)得挺不錯(cuò)的,這里分享給大家,供需要的朋友參考。
    2017-10-10

最新評(píng)論