Spring源码 – 核心接口BeanPostProcessor[通俗易懂]

Spring源码 – 核心接口BeanPostProcessor[通俗易懂]Spring源码-核心接口BeanPostProcessor

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

Spring源码 – 核心接口BeanPostProcessor

Spring版本:Spring 5.3.13-release


# 1、核心接口BeanPostProcessor

BeanPostProcessor接口我们一般称为后置处理器或者增强器。

BeanPostProcessor接口是Spring本着开闭原则(面对修改关闭面对扩展开放)设计的一个接口。

BeanPostProcessor接口允许开发者在Bean实例化前后对Bean做一些定制化处理,如修改BeanDefinition等。

BeanPostProcessor接口代码:

public interface BeanPostProcessor { 
   

	/** * Apply this {@code BeanPostProcessor} to the given new bean instance <i>before</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
   
		return bean;
	}

	/** * Apply this {@code BeanPostProcessor} to the given new bean instance <i>after</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding {@code bean instanceof FactoryBean} checks. * <p>This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other {@code BeanPostProcessor} callbacks. * <p>The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
   
		return bean;
	}

}

BeanPostProcessor接口中定义了两个方法:

  • 1、postProcessBeforeInitialization(Object bean, String beanName):在Bean实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化操作。
  • 2、postProcessAfterInitialization(Object bean, String beanName):在Bean实例化、依赖注入、初始化完毕时执行。

可以看出postProcessBeforeInitialization()方法是Spring在Bean进行初始化之前的回调,postProcessAfterInitialization()方法是Spring在Bean初始化完成之后的回调。


# 2、BeanPostProcessor的注册

BeanPostProcessor的注册是在Spring进行容器刷新中的AbstractApplicationContext#registerBeanPostProcessors()方法中完成的。而具体的逻辑实现Spring则是委派给PostProcessorRegistrationDelegate#registerBeanPostProcessors()方法进行具体的注册实现。

	public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { 
   

		// WARNING: Although it may appear that the body of this method can be easily
		// refactored to avoid the use of multiple loops and multiple lists, the use
		// of multiple lists and multiple passes over the names of processors is
		// intentional. We must ensure that we honor the contracts for PriorityOrdered
		// and Ordered processors. Specifically, we must NOT cause processors to be
		// instantiated (via getBean() invocations) or registered in the ApplicationContext
		// in the wrong order.
		//
		// Before submitting a pull request (PR) to change this method, please review the
		// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
		// to ensure that your proposal does not result in a breaking change:
		// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

		// 获取所有的 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.
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;

		// BeanPostProcessorChecker 是一个普通的信息打印
		// 可能存在有些情况当 Spring 配置中的后置处理器还没有被注册就已经开始 Bean 的实例化了, 这个时候就会打印出 BeanPostProcessorChecker 中设定的信息
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		// 用于保存实现了 PriorityOrdered 排序接口的 BeanPostProcessor
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		// 用于保存 MergedBeanDefinitionPostProcessor 类型 BeanPostProcessor
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		// 用于保存实现了 Ordered 排序接口的 BeanPostProcessor 的 BeanName
		List<String> orderedPostProcessorNames = new ArrayList<>();
		// 用于保存没有实现任何排序接口的 BeanPostProcessor 的 BeanName
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		// 遍历所有的 BeanPostProcessor 的 BeanName, 按照不同筛选条件放入相应的容器中
		for (String ppName : postProcessorNames) { 
   
			// 如果实现了 PriorityOrdered 排序接口
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { 
   
				// 根据 BeanName 获取 Bean 实例并放入 priorityOrderedPostProcessors 中
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				// 如果是 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor 继续放入 internalPostProcessors 中
				if (pp instanceof MergedBeanDefinitionPostProcessor) { 
   
					internalPostProcessors.add(pp);
				}
			}
			// 如果实现了 Ordered 排序接口
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { 
   
				// 将 BeanName 放入 orderedPostProcessorNames 中
				orderedPostProcessorNames.add(ppName);
			}
			// 没有实现任何排序接口
			else { 
   
				// 将 BeanName 放入 nonOrderedPostProcessorNames 中
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		// 对实现了 PriorityOrdered 排序接口的 BeanPostProcessor 进行排序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		// 根据排序结果依次注册 BeanPostProcessor 到 BeanFactory 中,
		// 实际就是将排序后的 BeanPostProcessor 保存到 AbstractBeanFactory#beanPostProcessors 容器中
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		// 创建一个容器用于存放实现了 Ordered 排序接口的 BeanPostProcessor
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		// 遍历实现了 Ordered 排序接口的 BeanPostProcessor 的 BeanName
		for (String ppName : orderedPostProcessorNames) { 
   
			// 根据 BeanName 获取 Bean 实例并放入 orderedPostProcessors 中
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			// 如果是 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor 继续放入 internalPostProcessors 中
			if (pp instanceof MergedBeanDefinitionPostProcessor) { 
   
				internalPostProcessors.add(pp);
			}
		}
		// 对实现了 Ordered 排序接口的 BeanPostProcessor 的 Bean 实例进行排序
		sortPostProcessors(orderedPostProcessors, beanFactory);
		// 根据排序结果依次注册 BeanPostProcessor 到 BeanFactory 中,
		// 实际就是将排序后的 BeanPostProcessor 保存到 AbstractBeanFactory#beanPostProcessors 容器中
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		// 创建一个容器用于存放没有实现任何排序接口的 BeanPostProcessor
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		// 遍历没有实现任何排序接口的 BeanPostProcessor 的 BeanName
		for (String ppName : nonOrderedPostProcessorNames) { 
   
			// 根据 BeanName 获取 Bean 实例并放入 nonOrderedPostProcessors 中
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			// 如果是 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor 继续放入 internalPostProcessors 中
			if (pp instanceof MergedBeanDefinitionPostProcessor) { 
   
				internalPostProcessors.add(pp);
			}
		}
		// 注册 BeanPostProcessor 到 BeanFactory 中
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		// 对 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor 进行排序
		sortPostProcessors(internalPostProcessors, beanFactory);
		// 注册 BeanPostProcessor 到 BeanFactory 中, 注册时会先执行移除已存在的 BeanPostProcessor 然后在进行添加
		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).
		// 添加处理用户自定义 ApplicationListener 注册和销毁的 BeanPostProcessor
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

BeanPostProcessor的注册逻辑也是非常清晰:按照BeanPostProcessor实现的排序接口依次进行注册。

需要注意的是,这里仅仅是完成BeanPostProcessor的注册工作,此时BeanPostProcessor类型的Bean已经注册到Spring的IOC容器中,并且由AbstractBeanFactory中的beanPostProcessors持有一份已注册的缓存副本。


# 3、BeanPostProcessor的激活

BeanPostProcessor的激活是在Spring初始化Bean时完成。

AbstractAutowireCapableBeanFactory#initializeBean()代码:

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { 
   
		// 如果安全管理器不为空
		if (System.getSecurityManager() != null) { 
   
			// 以特权的方式执行回调 Bean 中的 Aware 接口方法
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 
   
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else { 
   
			// Aware 接口处理器, 调用 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		// 如果 RootBeanDefinition 不为空 || RootBeanDefinition 不是 synthetic。一般指只有 AOP 相关的 PointCut 配置或者 Advice 配置才会将 synthetic 设置为 true
		if (mbd == null || !mbd.isSynthetic()) { 
   
			// 将 BeanPostProcessor 应用到给定的现有 Bean 实例, 调用它们的 PostProcessorsBeforeInitialization 初始化方法
			// 返回的 Bean 实例可能是原始 Bean 包装器
			// 执行 applyBeanPostProcessorsBeforeInitialization 方法后会将 ApplicationContext 注入进来
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try { 
   
			// 调用初始化方法, 先调用 Bean 的 InitializeBean 接口方法, 后调用 Bean 的自定义初始化方法
			// invokeInitMethods() 方法的作用是执行初始化方法, 这些初始化方法包括 :
			// 1.在 XML 文件中的 <bean></bean> 标签中使用的 init-method 属性的 Bean 初始化方法;
			// 2.在 @Bean 注解中使用 initMethod 属性指定的 Bean 初始化方法;
			// 3.使用 @PostConstruct 注解标注的方法;
			// 4.实现 InitializingBean 接口的方法等;
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) { 
   
			// 捕捉调用初始化方法时抛出的异常, 重新抛出 Bean 创建异常 : 调用初始化方法失败
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		// 如果 RootBeanDefinition 不为空 || RootBeanDefinition 不是 synthetic
		if (mbd == null || !mbd.isSynthetic()) { 
   
			// 将 BeanPostProcessor 应用到给定的现有 Bean 实例, 调用它们的 postProcessAfterInitialization 方法
			// 返回的 Bean 实例可能是原始 Bean 包装器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		// 返回包装后的 Bean
		return wrappedBean;
	}

可以看到在Spring在Bean完全实例化之前调用了applyBeanPostProcessorsBeforeInitialization()方法,在Bean完全实例化之后调用了applyBeanPostProcessorsAfterInitialization()方法。

AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization()代码:

	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException { 
   

		// 初始化返回结果为 existingBean
		Object result = existingBean;
		// 遍历, 该工厂创建的 Bean 的 BeanPostProcessors 列表
		for (BeanPostProcessor processor : getBeanPostProcessors()) { 
   
			// postProcessBeforeInitialization : 在任何 Bean 初始化回调之前(如初始化 Bean 的 afterPropertiesSet 或自定义的 init 方法)
			// 将此 BeanPostProcessor 应用到给定的新 Bean 实例。Bean 已经填充了属性值。返回的 Bean 实例可能是原始 Bean 的包装器
			// 默认实现按原样返回给定的 Bean
			Object current = processor.postProcessBeforeInitialization(result, beanName);

			// 如果 current 为空。即一旦 Bean 的 BeanPostProcessors 中的某一个增强处理器返回 null, 后续 BeanPostProcessor 对象的 postProcessBeforeInitialization 方法不在执行, 直接退出后续循环
			if (current == null) { 
   
				// 直接返回 result, 中断其后续的 BeanPostProcessor 处理器
				return result;
			}
			// 让 result 引用 processor 返回的结果, 使其经过所有 BeanPostProcessor 对象的后置处理器的层层包装
			result = current;
		}
		// 返回经过所有 BeanPostProcessor 对象的后置处理器的层层包装后的 result
		return result;
	}

Spring会获取在AbstractBeanFactory中持有的已经注册完成的BeanPostProcessor实例。获取到之后根据顺序依次激活。调用postProcessBeforeInitialization()对Bean进行包装并返回。如果其中某一个BeanPostProcessor返回的结果为null,则中断执行后续的BeanPostProcessor,直接返回当前结果。

AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization()代码:

	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException { 
   

		Object result = existingBean;

		// 获取创建 Bean 实例对象过程中所有的 BeanPostProcessors(Bean后置处理器)
		for (BeanPostProcessor processor : getBeanPostProcessors()) { 
   
			// 如果 Bean 被子类标记为代理, 则使用配置的拦截器创建一个代理
			Object current = processor.postProcessAfterInitialization(result, beanName);
			// 如果某一个 BeanPostProcessor 返回 null, 则中断后续所有 BeanPostProcessor 的激活, 直接放回当前结果
			if (current == null) { 
   
				return result;
			}
			// 让 result 引用 processor 返回的结果, 使其经过所有 BeanPostProcessor 对象的后置处理器的层层包装
			result = current;
		}
		// 返回经过所有 BeanPostProcessor 对象的后置处理器的层层包装后的 result
		return result;
	}

逻辑与applyBeanPostProcessorsBeforeInitialization()方法类型。也是先获取所有的BeanPsotProcessor实例副本,然后依次执行激活。

GitHub源码地址:https://github.com/kapbc/kapcb-spring-source/tree/master/Spring-Framework-v5.3.13

备注:此文为笔者学习Spring源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/170022.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Chrome 添加自定义搜索引擎「建议收藏」

    Chrome 添加自定义搜索引擎「建议收藏」在Chrome浏览器地址栏输入:chrome://settings/searchEngines进入管理搜索引擎点击其他搜索引擎右上角的“添加”按钮在输入界面自定义你的引擎,比如我这里添加了PIP的清华镜像点,以便于搜索我想要的第三方库该搜索引擎是通过关键字触发的,比如我用的“-pip”关键字在地址栏输入“-pip”,按tab键即可触发…

    2022年7月13日
  • 【Maven学习】Maven打包生成普通jar包、可运行jar包、包含所有依赖的jar包

    【Maven学习】Maven打包生成普通jar包、可运行jar包、包含所有依赖的jar包使用maven构建工具可以将工程打包生成普通的jar包、可运行的jar包,也可以将所有依赖一起打包生成jar;一、普通的jar包普通的jar包只包含工程源码编译出的class文件以及资源文件,而不包含任何依赖;同时还包括pom文件,说明该包的依赖信息;在工程pom文件下这样写,可生成普通的jar包:jar或者,不写,因为packaging默认打包类型为

    2022年5月30日
  • 40 道基础Dubbo 面试题及答案

    40 道基础Dubbo 面试题及答案转载自史上最全40道Dubbo面试题及答案,看完碾压面试官想往高处走,怎么能不懂Dubbo?Dubbo是国内最出名的分布式服务框架,也是Java程序员必备的必会的框架之一。Dubbo更是中高级面试过程中经常会问的技术,无论你是否用过,你都必须熟悉。下面我为大家准备了一些Dubbo常见的的面试题,一些是我经常问别人的,一些是我过去面试遇到的一些问题,总结给大家,希…

    2022年5月10日
  • java decimal保留两位小数_bigdecimal两位小数

    java decimal保留两位小数_bigdecimal两位小数那么,如何学习Kafka源码??我觉得最高效的方式就是去读最核心的源码,先看一张 Kafka结构图 以及 Kafka源码全景图梳理一下关于 Kafka框架,找到学习的重点。其次,我要说的就是一个Kafka源码解析的文档——《Kafka源码解析与实战》前5章分别是:Kafka简介、Kafka的架构、Broker概述、Broker的基本模块、Broker的控制管理模块**第1章Kafka简介:**介绍Kafka诞生的背景、Kafka在Linked

    2022年9月23日
  • BeanUtils.populate 使用笔记

    BeanUtils.populate 使用笔记最近在学习网站开发,在后端获取网站请求数据的时候用到了BeanUtils.populate()方法,具体用法是:BeanUtils.populate(objectobj,Map<String,String[]>map);于是我就在想这个方法是怎么把map中的数据封装到obj对象里的。打开源码看,看别人写的代码是真难受,看了半天还是没看懂。上网搜了一下,发现多数都是在讲用法…

    2022年7月13日
  • 怎么看idea是否激活_最新在线免费激活

    (怎么看idea是否激活)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.htmlCJM5ZJBPHS-eyJsaWNlbnNlSWQi…

    2022年3月31日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号