Sping源码(八)—registerBeanPostProcessors

序言

之前我们用大量的篇幅介绍过invokeBeanFactoryPostProcessors()方法的执行流程。

invokeBeanFactoryPostProcessors的主要逻辑就是遍历执行实现了BeanDefinitionRegistryPostProcesso类(主要是针对BeanDefinition的操作)和BeanFactoryPostProcessor(主要针对BeanFacroty的操作)

我们这篇文章里要介绍的registerBeanPostProcessors()方法 和 invokeBeanFactoryPostProcessors()方法类似,作用对象是Bean,用于在 Spring 容器实例化、配置和初始化 bean 的过程中提供自定义的扩展点。

源码

获取系统中实现BeanPostProcessor的类并进行分类,添加到BeanFacroty中。处理逻辑和BeanPosrProcessor基本相似。

java 复制代码
	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		//获取所有实现了BeanPostProcessor类的BeanName
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.

		//这里的 +1,应该是为了为下方的 new BeanPostProcessorChecker 留个位置
		//创建的BeanPostProcessorChecker是用来
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.

		//用来存放实现riorityOrdered的BeanPostProcessor
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		//用来存放实现MergedBeanDefinitionPostProcessor的BeanPostProcessor
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		//用来存放实现Ordered的BeanPostProcessor
		List<String> orderedPostProcessorNames = new ArrayList<>();
		//用来存放没有实现排序接口的BeanPostProcessor
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();

		//遍历获取所有的BeanPostProcessor
		for (String ppName : postProcessorNames) {
			//判断是否实现了PriorityOrdered接口
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//获取BeanPostProcessor
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				//判断是否实现了MergedBeanDefinitionPostProcessor接口
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			//如果实现了Ordered接口,则添加到orderedPostProcessorNames中
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				//否则就是没有实现排序接口的类
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.

		//根据优先级进行排序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//注册(循环添加到BeanFactory的beanPostProcessors集合中)实现priorityOrder接口的BeanPostProcessor
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.

		//注册(循环添加到BeanFactory的beanPostProcessors集合中)实现Ordered接口的BeanPostProcessor
		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.
		//最后注册(循环添加到BeanFactory的beanPostProcessors集合中)没有实现排序接口的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);

		// Finally, re-register all internal BeanPostProcessors.

		//重新注册(循环添加到BeanFactory的beanPostProcessors集合中)实现MergedBeanDefinitionPostProcessor接口的BeanPostProcessor
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).

		//注册ApplicationListenerDetector,
		// 其实refresh()主流程方法下的prepareBeanFactory(beanFactory)方法中已经向beanFactory中添加了ApplicationListenerDetector
		//这里是重新注册,保证ApplicationListenerDetector在beanPostProcessors集合的最后
		//目的是检测并管理应用程序上下文中的事件监听器。
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

扩展

值得说的地方是Spirng提供了几个比较重要的BeanPostProcessor接口可以用来进行扩展。因为其与四个接口都继承自BeanPostProcessor所以BeanPostProcessor中的方法他们也都有。

挨个接口来看看里面都有什么。

BeanPostProcessor

bean的后置处理器接口,在依赖注入的初始化方法前后进行调用。

java 复制代码
/**
 * bean的后置处理器接口,在依赖注入的初始化方法前后进行调用
 */
public interface BeanPostProcessor {

	/**
	 * 初始化方法调用前要进行的处理逻辑
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * 在初始化方法指定后要进行的处理逻辑
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

InstantiationAwareBeanPostProcessor

新增了属性注入的方法。

java 复制代码
/**
 * 继承自BeanPostProcessor,添加了实例化前,实例化后,属性注入后的处理方法
 */
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	//省略BeanPostProcessor方法...

	/**
	 * 当使用注解的时候,通过这个方法来完成属性的注入
	 */
	@Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
			throws BeansException {

		return null;
	}

	/**
	 * 属性注入后执行的方法,在5.1版本被废弃
	 */
	@Deprecated
	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		return pvs;
	}

}

SmartInstantiationAwareBeanPostProcessor

继承自InstantiationAwareBeanPostProcessor ,额外增加3个方法。

java 复制代码
/**
 * 继承自InstantiationAwareBeanPostProcessor接口,增加了三个额外处理的方法,由spring内部使用
 *
 */
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

	/**
	 * 预测bean的类型,主要是在bean还没有创建前我们需要获取bean的类型
	 *
	 */
	@Nullable
	default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}

	/**
	 * 完成对构造函数的解析和推断
	 */
	@Nullable
	default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
			throws BeansException {

		return null;
	}

	/**
	 * 解决循环依赖问题,通过此方法提前暴露一个合格的对象
	 *
	 */
	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

MergedBeanDefinitionPostProcessor

两个BeanDefinition合并时调用。

java 复制代码
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

	/**
	 *spring通过此方法找出所有需要注入的字段,同时做缓存
	 */
	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

	/**
	 * 用于在BeanDefinition被修改后,清除容器的缓存
	 */
	default void resetBeanDefinition(String beanName) {
	}
}

DestructionAwareBeanPostProcessor

判断Bean是否应该销毁和销毁时调用

java 复制代码
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {

	/**
	 * 在bean被销毁前调用
	 */
	void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

	/**
	 * 判断是否要进行销毁,一般情况下都需要
	 */
	default boolean requiresDestruction(Object bean) {
		return true;
	}
}
相关推荐
杨运交29 分钟前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring
Geek-Chow1 小时前
CountDownLatch in Java
java
SL_staff1 小时前
从RBAC到场景化授权:《无忧·企业文档》三级权限模型的技术实践解析
java·开源·产品
传奇开心果编程2 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff2 小时前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈
滕州市燕猫虎计算机科技工作室个体工商户2 小时前
IDEA:Command line is too long
java·ide·intellij-idea
步行cgn3 小时前
Spring p 命名空间注入详解
java·前端·spring
YatHinLay3 小时前
MyBatis 流式查询实战:ResultHandler 处理海量数据
java
天天被压力3 小时前
【跨市场数据实战 #08】可转债折价机会怎么筛:3个接口抓比价、列表和实时盘口
java·人工智能·python
张某布响丸辣4 小时前
附件下载的安全边界:路径白名单、NAS 哨兵文件与 Redis Lua 一次性令牌
java·redis·redis lua·nas哨兵