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源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • qaManager

    qaManager

  • 数学函数图像处理_matlab基本图像处理

    数学函数图像处理_matlab基本图像处理文章目录1.imdilate2.imresize3.imfinfo4.imcomplement总结1.imdilate功能:进行膨胀操作介绍用法:IM2=imdilate(IM,SE)对灰度图像或二值图像IM进行膨胀操作,返回结果图像IM2。SE为由strel函数生成的结构元素对象。IM2=imdilate(IM,NHOOD)对灰度图像或二值图像IM进行膨胀操作,返回结果图像IM2。参量NHOOD是一个由O和1组成的矩阵,指定邻域。IM2=imdilate(…,SHAPE)对图

  • java实现发送邮件工具[通俗易懂]

    java实现发送邮件工具[通俗易懂]java实现发送邮件的功能:首先需要导入mail.jar;然后需要写发送方法:1、邮箱发送封装工具类:packagecom.wxjiameng.utils;importjava.util.Date;importjava.util.Properties;importjavax.activation.DataHandler;importjavax.activation.FileDa

  • c语言头文件instr,C/C++常用函数合集「建议收藏」

    目录C标准库头文件1.memset()2.memcpy()3.strcpy()4.strncpy()5.strcat()6.getline()7.strlen()头文件1.tolower()/toupper()2.isalpha(),isdigit(),isprint()头文件1.pow()2.floor()3.ceil()4.atan()STL头文件1.min(),max()函数2.lower_…

  • 使用 parted 对单个磁盘进行分区并进行配额「建议收藏」

    使用 parted 对单个磁盘进行分区并进行配额「建议收藏」文章目录1.实验要求2.实验步骤3.我的一次实验步骤1.实验要求虚拟机新增一个硬盘,大小大于10G,使用parted工具对磁盘进行分区,分区类型为ext4对新增分区设置磁盘配额,限制lisi用户最多允许使用200M的容量大小并最多允许创建10个文件2.实验步骤准备一个新虚拟机,我们用新环境进行实验VMware添加一块20G硬盘echo”—“>/sys/class/scsi_host/host0/scan#扫描主机fdis

  • winhttp 访问https_WinHttp支持HTTPS下载「建议收藏」

    winhttp 访问https_WinHttp支持HTTPS下载「建议收藏」WinHttp支持HTTPS下载#include”windows.h”#include”winhttp.h”#include”wchar.h”#pragmacomment(lib,”Winhttp.lib”)//SSL(SecureSocketsLayer)example//compileforconsolevoidmain(){HINTERNEThOpen=0;H…

发表回复

您的电子邮箱地址不会被公开。

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