Spring源码阅读之registerBeanPostProcessors()源码分析

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

上篇文章我们分析了invokeBeanFactoryPostProcessors()方法的实现,主要是BeanFactoryBeanDefinition定义在实例化之前做一些前置操作。接下来本文来看看registerBeanPostProcessors()的实现,上篇文章留了一个疑问,大家是否还记得?我们在本篇文章揭晓答案,本篇先来解读源码,后面附上测试用例。

  1. 回到AbstractApplicationContext.refresh()方法的registerBeanPostProcessors()地方,我们来看看实现,从方法中可以看出,调用了PostProcessorRegistrationDelegate类的静态方法。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

  1. PostProcessorRegistrationDelegate.registerBeanPostProcessors方法用于注册所有BeanPostProcessor实例(该方法比较长,但是流程很清晰,耐心开完)。看源码前首先需要明白两个类:
  • BeanPostProcessor: 一切BeanPostProcessor实例都需要直接或间接该接口。
  • MergedBeanDefinitionPostProcessor: 是一个接口,实现了BeanPostProcessor接口,并给出了一个方法。所以实现了该接口的类比实现了BeanPostProcessor类的优先级更高,功能更丰富。
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext)
{
// Step1:获取所有直接或间接实现了BeanPostProcessor接口的BeanDefinition对应的processor名字。内部实现见源码分析3
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;
// Step2:添加一个BeanPostProcessor检查器,该检查器的作用:是在创建BeanPostProcessor时记录日志、创建BeanPostProcessor发生异常时记录日志等等操作。
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// Step3:存放实现了PriorityOrdered接口的BeanPostProcessor,其优先级最高。
// PriorityOrdered接口作用:用于对BeanPostProcessor进行优先级排序的。和上一篇关于BeanFactoryPostProcessor的排序功能一样。
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// Step4:存放内部实现的BeanPostProcessor。
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// Step5:存放实现了Ordered接口的BeanPostProcessor,其优先级低于PriorityOrdered接口
// Ordered接口作用:也是排序功能。
List<String> orderedPostProcessorNames = new ArrayList<>();
// Step6:存放除去内部的和有优先级的BeanPostProcessor后,剩余的BeanPostProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// Step7:遍历BeanPostProcessor对应的名字,进行分堆和创建Bean实例操作。关于创建Bean实例在后面创建Bean实例专门介绍,这里不展开。
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);
}
}

// First, register the BeanPostProcessors that implement PriorityOrdered.
// Step8:对PriorityOrdered相关的BeanPostProcessor进行排序操作,排序的依据是重写了PriorityOrdered的getOrder的返回值
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Step9:将排序后的BeanPostProcessor一次注册到BeanFactory里面。
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

// Next, register the BeanPostProcessors that implement Ordered.
// Step10:遍历实现了Ordered接口的BeanPostProcessor,如果改processor实现了MergedBeanDefinitionPostProcessor接口,将其加入到内部的BeanPostProcessor集合里面。
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// Step11:排序
sortPostProcessors(orderedPostProcessors, beanFactory);
// Step12:注册
registerBeanPostProcessors(beanFactory, orderedPostProcessors);

// Now, register all regular BeanPostProcessors.
// Step13:对无优先级的BeanPostProcessor进行遍历,将实现了MergedBeanDefinitionPostProcessor接口的加入到内部BeanPostProcessor的集合中
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// Step14:没有先后顺序,一次注册这些Bean实例到BeanFactory里面。
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

// Finally, re-register all internal BeanPostProcessors.
// Step15:最后对所有的内部BeanPostProcessor实例进行排序操作,并将其注册到BeanFactory里面。
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).
// Step16:对BeanFactory添加一个一个全局的监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

  1. 我们来看下BeanPostProcessor对应的beanName是怎么获取到的。
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
// Step1:当前BeanFactory是否冻结,冻结返回true(就是说当前BeanFactory的BeanDefinition定义是否不可以被修改)
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
// Step2:从当前BeanFactory的缓存里面获取对应的BeanPostProcessor名字。如果有直接返回(在Spring源码中大量用到了这种缓存机制来提升Spring容器初始化的速度)
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
// Step3:都没有取到,则根据type去加载相应的名字
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}

  1. 来看看根据type如果获取到对应的BeanPostProcessor名字,这里稍微比较复杂一点,归纳一下其实就是遍历所有的beanName,然后拿type去匹配,如果能匹配的上就认为是目标的BeanPostProcessor对应的baneName
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<>();

// Check all bean definitions.
// Step1:遍历当前BeanFactory里面所有的beanNames
for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name
// is not defined as alias for some other bean.
// Setp1.1:判断当前beanName是否是别名,所以if里面的逻辑是针对非别名的beanName处理。
if (!isAlias(beanName)) {
try {
// Step1.1.1:根据beanName获取对应的BeanDefinition定义,具体逻辑之前介绍过,在这里就不展开了。
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
// Step1.1.2:检查BeanDefinition定义是否完整。即当前BeanDefinition定义是:非抽象的 && (提前加载 || (有对应的BeanClass || 非懒加载 || 允许提前加载bean)&& 是否提前初始化指定类型的bean)
// 总结大概意思就是当前BeanDefinition定义是非抽象的且可以提前加载
if (!mbd.isAbstract() && (allowEagerInit ||
(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// In case of FactoryBean, match object created by FactoryBean.
// Setp1.1.2.1:根据beanName和对应的BeanDefinition定义判断是否是一个FactoryBean。
boolean isFactoryBean = isFactoryBean(beanName, mbd);
// Step1.1.2.2:返回此BeanDefinition被修饰的BeanDefinitionHolder对象。
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
// Step1.1.2.3:判断beanName和对应的BeanDefinition是否匹配
boolean matchFound =
(allowEagerInit || !isFactoryBean ||
(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
(includeNonSingletons ||
(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
isTypeMatch(beanName, type);
// Step1.1.2.4:没匹配到 %% 是BeanFactory,则添加BeanFactory的前缀,在匹配一次。
if (!matchFound && isFactoryBean) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
}
// Step1.1.2.5:匹配到则将beanName加到结果集中
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
catch (BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
}
}

// Check manually registered singletons too.
// Step2:检查手动注册的单例Bean
for (String beanName : this.manualSingletonNames) {
try {
// In case of FactoryBean, match object created by FactoryBean.
// Step2.1:是一个FactoryBean并且匹配到了,则加入到结果集中
if (isFactoryBean(beanName)) {
if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
result.add(beanName);
// Match found for this bean: do not match FactoryBean itself anymore.
continue;
}
// In case of FactoryBean, try to match FactoryBean itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
}
// Match raw bean instance (might be raw FactoryBean).
// Step2.2:非FactoryBean并且匹配到了,则加入到结果集中
if (isTypeMatch(beanName, type)) {
result.add(beanName);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Shouldn't happen - probably a result of circular reference resolution...
if (logger.isDebugEnabled()) {
logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);
}
}
}
// Step3:返回匹配到的结果集
return StringUtils.toStringArray(result);
}

5. 以上即为源码的分析,所以的工作就是将BeanPostProcessor注册到BeanFactory里面,然后在 bean 实例初始化前做一些工作(关于这个我们在介绍 bean 实例初始化的地方会介绍)。接下来,来看一个例子来理解一下整个过程。
// 使用方法比较简单,我们创建一个MyBeanPostProcessor,其实现了BeanPostProcessor接口和Ordered的接口
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

/**
* @author zxz
* 自定义BeanPostProcessor
*/

public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {
public int getOrder() {
// 这个返回值是用来对实现了Ordered接口的BeanPostProcessor进行排序的
return 0;
}

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization,该方法是在Bean实例初始化前被调用,执行一些特殊的逻辑");
// 这里写自己要做的特殊逻辑
if (bean instanceof UserService) {
System.out.println("UserService instance bean before");
}
return bean;
}

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessAfterInitialization,该方法实在Bean实例初始化后被调用,执行特殊的逻辑");
// 这里写自己要做的特殊逻辑
if (bean instanceof UserService) {
System.out.println("UserService instance bean after");
}
return bean;
}
}
// xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
>

<bean id="userService" class="UserServiceImpl"/>
<!-- 注入自定义的BeanPostProcessor -->
<bean id="myBeanPostProcessor" class="MyBeanPostProcessor"/>
</beans>
// 单测
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class JuniteTest {

@Test
public void testBeanPostProcessor() {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserService userService = context.getBean(UserService.class);
userService.save();
}
}

Spring源码阅读之registerBeanPostProcessors()源码分析从输出结果来看,首先调用了重写的postProcessBeforeInitialization()postProcessAfterInitialization()方法。然后在UserServicesave方法。


6. 以上内容为BeanPostProcessor注册的全流程。现在来回答一下上篇文章留下的问题,invokeBeanFactoryPostProcessors()registerBeanPostProcessors()区别?
  • invokeBeanFactoryPostProcessors():操作的对象是BeanDefinition定义,在此阶段我们随意修改BeanDefinition定义的属性相关。BeanFactoryPostProcessor只提供了一个方法:postProcessBeanFactory()
  • registerBeanPostProcessors():操作的对象是BeanDefinition定义对应的 Bean 实例,BeanPostProcessor提供了两个方法:postProcessBeforeInitialization()postProcessAfterInitialization()

总结

registerBeanPostProcessors方法主要功能是将所有实现了BeanPostProcessor接口或者实现了MergedBeanDefinitionPostProcessor接口的类对应的实例注册到BeanFactory中(注意是将 Bean 实例注册到BeanFactory里面)。

在该方法内部将BeanPostProcessor分为四类,分别是实现了PriorityOrdered接口的、实现了Ordered接口的、内部的和普通的。按照优先级依次排序将这四类BeanPostProcessor注册到BeanFactory里面。

BeanPostProcessor提供的两个方法的调用时机是在 Bean 实例初始化前后的时候被调用。

下一篇我们就来介绍 Spring 最核心的一个方法:finishBeanFactoryInitialization(),看看它是怎么把BeanDefinition定义转化成对应的 Bean 实例的,敬请期待。


Spring源码阅读之registerBeanPostProcessors()源码分析

欢迎关注我,共同学习

原文始发于微信公众号(z小赵):Spring源码阅读之registerBeanPostProcessors()源码分析