Spring IOC 容器源码分析 - getBean调用方法解析(六) -- Bean的初始化之BeanPostProcessor
2021-02-15 20:20
标签:block rabl hello 它的 style 标记 sde count 否则 Spring 作为优秀的开源框架,它为我们提供了丰富的可扩展点,除了前面提到的 Aware 接口,还包括其他部分,其中一个很重要的就是 BeanPostProcessor。这篇文章主要介绍 BeanPostProcessor 的使用以及其实现原理。我们先看 BeanPostProcessor 的定位: BeanPostProcessor 的作用:在 Bean 完成实例化后,如果我们需要对其进行一些配置、增加一些自己的处理逻辑,那么请使用 BeanPostProcessor。 首先定义一个类,该类实现BeanPostProcessor接口,代码如下: 测试方法如下: 运行结果: 运行结果比较奇怪,为什么没有执行 #postProcessBeforeInitialization(...) 和 #postProcessAfterInitialization(...) 方法呢? 我们 debug 跟踪下代码,这两个方法在 AbstractAutowireCapableBeanFactory 的 #initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法处调用下,如下: 一起来看看applyBeanPostProcessorsBeforeInitialization 这段代码是通过迭代 ,所以肯定不会执行相应的 返回的 该方法是由 AbstractBeanFactory 的父类 BeanPostProcessor 可以理解为是 Spring 的一个工厂钩子(其实 Spring 提供一系列的钩子,如 Aware 、InitializingBean、DisposableBean),它是 Spring 提供的对象实例化阶段强有力的扩展点,允许 Spring 在实例化 bean 阶段对其进行定制化修改,比较常见的使用场景是处理标记接口实现类或者为当前对象提供代理实现(例如 AOP)。 一般普通的 BeanFactory 是不支持自动注册 BeanPostProcessor 的,需要我们手动调用
代码层次上面已经贴出来,这里再贴一次: 两者源码如下: ApplicationContext 实现自动注册的原因,在于我们构造一个 ApplicationContext 实例对象的时候会调用 【排序】很简单,如果 至此,BeanPostProcessor 已经分析完毕了,这里简单总结下: Spring IOC 容器源码分析 - getBean调用方法解析(六) -- Bean的初始化之BeanPostProcessor 标签:block rabl hello 它的 style 标记 sde count 否则 原文地址:https://www.cnblogs.com/w2116o2115/p/12712739.html1.BeanPostProcessor接口
2.BeanPostProcessor实例
public class BeanPostProcessorTest implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean [" + beanName + "] 开始初始化");
// 这里一定要返回 bean,不能返回 null
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean [" + beanName + "] 完成初始化");
return bean;
}
public void display(){
System.out.println("hello BeanPostProcessor!!!");
}
}
ClassPathResource resource = new ClassPathResource("spring.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
BeanPostProcessorTest test = (BeanPostProcessorTest) factory.getBean("beanPostProcessorTest");
test.display();
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {//通过getBeanPostProcessors()获取所有
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
#getBeanPostProcessors()
方法返回的结果集来调用 BeanPostProcessor 的 #postProcessBeforeInitialization(Object bean, String beanName)
方法,在我们的代码执行过过程中getBeanPostProcessors()返回为空#postProcessBeforeInitialization(Object bean, String beanName)
方法咯。怎么办?答案不言而喻:只需要 #getBeanPostProcessors()
方法,返回的结果集中存在至少一个元素即可,该方法定义如下:// AbstractBeanFactory.java
/** BeanPostProcessors to apply in createBean. */
private final List
beanPostProcessors
是一个 private
的 List ,也就是说只要该类中存在 beanPostProcessors.add(BeanPostProcessor beanPostProcessor)
的调用,我们就找到了入口,在类 AbstractBeanFactory 中找到了如下代码: public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
org.springframework.beans.factory.config.ConfigurableBeanFactory
接口定义,它的核心意思就是将指定 BeanPostProcessor 注册到该 BeanFactory 创建的 bean 中,同时它是按照插入的顺序进行注册的,完全忽略 Ordered 接口所表达任何排序语义(在 BeanPostProcessor 中我们提供一个 Ordered 顺序,这个后面讲解)。
#addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
方法,将定义的 BeanPostProcessor 注册到相应的 BeanFactory 中3.BeanPostProcessor基本原理
org.springframework.beans.factory.config.BeanPostProcessor
接口,代码如下: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;
}
}
#addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
方法进行注册。注册后的 BeanPostProcessor 适用于所有该 BeanFactory 创建的 bean,但是 ApplicationContext 可以在其 bean 定义中自动检测所有的 BeanPostProcessor 并自动完成注册,同时将他们应用到随后创建的任何 Bean 中。#postProcessBeforeInitialization(Object bean, String beanName)
和 #postProcessAfterInitialization(Object bean, String beanName)
两个方法,都接收一个 Object 类型的 bean
,一个 String 类型的 beanName
,其中 bean
是已经实例化了的 instanceBean
,能拿到这个你是不是可以对它为所欲为了? 这两个方法是初始化 bean
的前后置处理器,他们应用 #invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
方法的前后。如下图: protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 遍历 BeanPostProcessor 数组
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 处理
Object current = processor.postProcessBeforeInitialization(result, beanName);
// 返回空,则返回 result
if (current == null) {
return result;
}
// 修改 result
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 遍历 BeanPostProcessor
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 处理
Object current = processor.postProcessAfterInitialization(result, beanName);
// 返回空,则返回 result
if (current == null) {
return result;
}
// 修改 result
result = current;
}
return result;
}
3.1 自动检测并注册
#getBeanPostProcessors()
方法,返回的是 beanPostProcessors
集合,该集合里面存放就是我们自定义的 BeanPostProcessor ,如果该集合中存在元素则调用相应的方法,否则就直接返回 bean 了。这也是为什么使用 BeanFactory 容器是无法输出自定义 BeanPostProcessor 里面的内容,因为在 BeanFactory#getBean(...)
方法的过程中根本就没有将我们自定义的 BeanPostProcessor 注入进来,所以要想 BeanFactory 容器 的 BeanPostProcessor 生效我们必须手动调用 #addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
方法,将定义的 BeanPostProcessor 注册到相应的 BeanFactory 中。但是 ApplicationContext 不需要手动,因为 ApplicationContext 会自动检测并完成注册。#registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)
方法,将检测到的 BeanPostProcessor 注入到 ApplicationContext 容器中,同时应用到该容器创建的 bean 中。代码如下: public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取所有的 BeanPostProcessor 的 beanName
// 这些 beanName 都已经全部加载到容器中去,但是没有实例化
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 记录所有的beanProcessor数量
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// 注册 BeanPostProcessorChecker,它主要是用于在 BeanPostProcessor 实例化期间记录日志
// 当 Spring 中配置的后置处理器还没有注册就已经开始了 bean 的实例化过程,这个时候便会打印 BeanPostProcessorChecker 中的内容
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// PriorityOrdered 保证顺序
List
beanFactory
获取注册到该 BeanFactory 中所有 BeanPostProcessor 类型的 beanName
数组,其实就是找所有实现了 BeanPostProcessor 接口的 bean ,然后迭代这些 bean ,将其按照 PriorityOrdered、Ordered、无序的顺序,添加至相应的 List 集合中,最后依次调用 #sortPostProcessors(List> postProcessors, ConfigurableListableBeanFactory beanFactory)
方法来进行排序处理、 #registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List
方法来完成注册。beanFactory
为 DefaultListableBeanFactory ,则返回 BeanFactory 所依赖的比较器,否则反正默认的比较器(OrderComparator),然后调用 List#sort(Comparator super E> c)
方法即可。代码如下:// PostProcessorRegistrationDelegate.java
private static void sortPostProcessors(List> postProcessors, ConfigurableListableBeanFactory beanFactory) {
// 获得 Comparator 对象
Comparator
AbstractBeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
方法完成注册。代码如下:// PostProcessorRegistrationDelegate.java
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List
4.结语
AbstractBeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
方法来完成注册
文章标题:Spring IOC 容器源码分析 - getBean调用方法解析(六) -- Bean的初始化之BeanPostProcessor
文章链接:http://soscw.com/index.php/essay/55791.html