Spring后置处理器BeanPostProcessor的源码探究

前言

最近研究了一下spring的后置处理器,感觉挺有意思的,顺便记录一下研究过程吧。

BeanPostProcessor类图

老话说得好,看源码主要就是看接口,毕竟面向接口编程嘛,源码的接口实现一大堆,看接口就清晰明了很多了。
Spring后置处理器BeanPostProcessor的源码探究_第1张图片
从类图里面可以看出来,Spring底层提供的Bean的后置处理器的顶层几个接口,也就上图这些了。那咱们就挨个给他实现一下,看他的工作机制是什么。

研究过程

1、BeanPostProcessor的创建

咱们给他们所有提供的接口建一个实现类,然后分别给构造方法和实现的方法打上断点,如下图。
Spring后置处理器BeanPostProcessor的源码探究_第2张图片
只得一提的是,实现SmartInstantiationAwareBeanPostProcessor这个接口的时候,没有必须要我们重写的方法,这个时候只有跟进类里面去结合注释自己挑选几个方法来重写了。

准备好环境后,把我们写的这几个BeanPostProcessor注册进spring容器,启动容器。

观察堆栈,由于篇幅问题我就只展示关键部分了,首先进入的断点毫无以为就是构造方法了,入口就是看过spring源码都很熟悉的refresh()方法中的registerBeanPostProcessors(),看名字也能知道个七七八八,先注册BeanPostProcessors嘛,如下图。
Spring后置处理器BeanPostProcessor的源码探究_第3张图片
然后继续看堆栈信息,进到了PostProcessorRegistrationDelegate.registerBeanPostProcessors方法。

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
			
		//从中央仓库(DefaultListableBeanFactory)中根据指定类型查找类名。
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
	
		//加入spring自己内置的beanPostProcessor(BeanPostProcessorChecker)
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
		
		//把BeanPostProcessor优先级分类,实现PriorityOrdered接口的优先级最高、Ordered的次之,没实现接口的最后调用。
		//用于存储的分别是priorityOrderedPostProcessors 、orderedPostProcessorNames 、nonOrderedPostProcessorNames 
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		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)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		//注册实现了PriorityOrdered接口的BeanPostProcessors 
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		//注册实现了Ordered接口的BeanPostProcessors 
		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);

		//注册其他的BeanPostProcessors,咱们没实现排序接口,所以断点就在这。
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		//循环创建所有的BeanPostProcessors
		for (String ppName : nonOrderedPostProcessorNames) {
			//getBean(),spring里面的基本操作,有则取之,无则创建
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//把创建好的BeanPostProcessors,放入beanfacoty
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

关键代码的地方,我已经加上注释,现在所有的BeanPostProcessors,已经注册进spring容器里面去了,我们接下来看一下他什么时候工作的。

2、BeanPostProcessor的工作时机

首先第一个进来的,MySmartInstantiationAwareBeanPostProcessor的predictBeanType方法。
Spring后置处理器BeanPostProcessor的源码探究_第4张图片
是在refresh的registerListeners时候调用的,然后跳过普通方法,直接看关键地方,如下图,
Spring后置处理器BeanPostProcessor的源码探究_第5张图片
获取所有SmartInstantiationAwareBeanPostProcessor类型的BeanPostProcessor,然后挨个调用他们的predictBeanType方法。JAVA多态的经典应用。

下一个进入断点的是MyMergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法,是在refresh的finishBeanFactoryInitialization方法调用进去的。
Spring后置处理器BeanPostProcessor的源码探究_第6张图片
还是看关键部分的代码,见下图
Spring后置处理器BeanPostProcessor的源码探究_第7张图片
跟之前的后置处理器同样的配方。

研究成果

看到这里,我们就不难推测出一个结论,spring在底层很多地方预留了后置处理器的接口,用于让我们自定义给类的增强逻辑。当然,spring自身很多功能也是通过后置处理器完成对类的增强的,感兴趣的同学可以查看BeanPostProcessor的实现。

你可能感兴趣的:(spring,spring,java,后端)