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()方法是SpringBean进行初始化之前的回调,postProcessAfterInitialization()方法是SpringBean初始化完成之后的回调。


# 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已经注册到SpringIOC容器中,并且由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;
	}

可以看到在SpringBean完全实例化之前调用了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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • vs的安装包_vs2019制作安装包

    vs的安装包_vs2019制作安装包VS安装包注册com组件VS安装包注册com组件1.把你的com组件加入到打包程序。 2.在打包程序中找到该com组件,点击属性。在属性中有Register项,把值选择为vsdrfCOM即可。

    2022年8月22日
    3
  • 通达OA 工作流执行出现的异常现象处理(图文)

    通达OA 工作流执行出现的异常现象处理(图文)一个朋友用的工作流,突然说这里面多了很多人不应该看到这个流程的,就是在查询工作时,最上面多了一个“查阅信息”项,然后最下面多了很多人查询的记录。这个项目是从哪里来的呢?普通的流程倒也无所谓了,而有些流程如发文、任职等还是需要保密的,这样让大家查阅肯定是不行的。一开始以为是使用了工作流的转存文件柜的功能,实验了一下,这样转存后并不会在流程里关联查看到查阅信息。又实验了一下转发布公告,同样不是。最后咨

    2022年6月23日
    36
  • 【java系列】unix时间戳转Date[通俗易懂]

    【java系列】unix时间戳转Date[通俗易懂]unix时间戳转Date注意,不能直接使用Integer进行乘除和转换,需要转成bigDecimal去处理,否则转换出来的时间只会是1970-xxxxpackagehutoolTest;importcn.hutool.core.date.DateTime;importjava.math.BigDecimal;importjava.text.SimpleDateFormat;importjava.util.Date;publicclassDateTest{pub

    2022年6月25日
    26
  • ubuntu安装后如何配置_ubuntu device for boot loader

    ubuntu安装后如何配置_ubuntu device for boot loader一、安装软件包#aptinstallcoturn二、配置coturn1、复制DTLS、TLS支持的证书文件:#cp/usr/share/coturn/examples/etc/turn_server_cert.pem/etc/turn_server_cert.pem#cp/usr/share/coturn/examples/etc/turn_server_pkey.pem/etc/t…

    2025年6月13日
    0
  • RSA加密算法流程图

    RSA加密算法流程图RSA加密算法流程图

    2022年5月15日
    57
  • 数据挖掘选择题_数据挖掘算法例题

    数据挖掘选择题_数据挖掘算法例题目录一、填空题二、计算题一、填空题❃随着信息技术的高速发展,数据库应用的规模、范围和深度不断扩大,网络环境成为主流等等。产生“数据丰富而信息贫乏”现象。❃“数据丰富而信息贫乏”现象导致大数据概念。❃数据(Data)、信息(Information)和知识(Knowledge)是广义数据表现的不同形式。❃大数据时代的数据挖掘技术需求分析的流派:数据论、方法论、环境论、特征论…

    2022年9月4日
    2

发表回复

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

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