spring bean post processor

相关文章web

上一篇文章咱们聊了下 Aware 接口、今天咱们再来聊一下 BeanPostProcessor缓存

为了各位客官老爷们看代码方便、不贴代码了、直接截图架构

其实再 AbstractBeanFactory 中有一个 List 专门存放着全部的 BeanPostProcessorapp

private final List<BeanPostProcessor> beanPostProcessors;
复制代码

咱们先来一睹 BeanPostProcessor 的真容吧编辑器

就那么两个方法函数

咱们写个小例子玩玩呗post

运行 demo , 竟然没有打印出来学习

看来咱们须要手动注册一波this

defaultListableBeanFactory.addBeanPostProcessor(new Student());
复制代码

我擦、这波操做有点骚啊、还真别这么写正常编码的时候。再次运行编码

Student:postProcessBeforeInitialization:student
Student:postProcessAfterInitialization:student 复制代码

BeanFactory 就这么弱鸡吗 ? 记得 ApplicationContext 是不用咱们去注册的

咱们使用一下 ApplicationContext 吧那就

运行一波、可是个人填为啥仍是没打印呢、咱们看看发生了啥、

当建立好 bean 而后回调 BeanPostProcessor 的时候、咱们发现、在 beanPostProcessors 中并无 Student 这个对象、也就是没有加入注册进去

可是咱们在 ApplicationContext 初始化以后查看、发现它又在了、这、到底是怎么回事呢 ( 我怎么这么多屁话 )

我先把调用链给出来吧

ClassPathXmlApplicationContext构造函数-->refresh()-->registerBeanPostProcessors()
复制代码

registerBeanPostProcessors 看其名就知道它是干啥的了、

registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
 PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); } 复制代码

代码有点长、咱们一点点分析

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); 复制代码

这个代码就是先从已经注册的 beanDefinition 中找到全部实现了 BeanPostProcessorbeanName、而后反手就注册一个叫作 BeanPostProcessorCheckerBeanPostProcessor 。这个类有什么做用呢、下次必定跟你们一块儿学习一下、下次必定

List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); 复制代码

而后就定义了四个局部变量存放 beanName 或者 BeanPostProcessor 对象

  • priorityOrderedPostProcessors 这个是存放即实现了 BeanPostProcessor 又实现了 PriorityOrdered 接口的
  • internalPostProcessors 存放的实现了 PriorityOrderedMergedBeanDefinitionPostProcessor 接口的( MergedBeanDefinitionPostProcessor 继承 BeanPostProcessor ),能够认为 internalPostProcessorspriorityOrderedPostProcessors 的子集
  • orderedPostProcessorNames 存放实现了 Ordered 接口的
  • nonOrderedPostProcessorNames 捡漏上面都不是的
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)) {  // 为啥不在这里调用 getBean 方法、而是在下面的 for 循环中再调用、  orderedPostProcessorNames.add(ppName);  }  else {  // 为啥不在这里调用 getBean 方法、而是在下面的 for 循环中再调用、  nonOrderedPostProcessorNames.add(ppName);  } } 复制代码

上面的代码就是遍历获取到的实现了 BeanPostProcessor 接口的 beanName、若是它也实现了 PriorityOrdered 接口的、那就调用 getBean 方法获取其 bean、若是只是实现了 Ordered 接口或者都没实现的话、那么就直接加入到对应的 List 中。这里留个问题,为啥保存实现 PriorityOrdered 接口的就要保存其 bean、实现 Ordered 或者都没实现的为啥只是保存其 beanName 、在上面的 else if 和 else 里面 getBean 一下不就得了 ?

// 先进行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory); // 注册 registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); 复制代码

这里就是对实现了 PriorityOrdered 接口的 先进行排序、优先级高的先注册

List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {  BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);  orderedPostProcessors.add(pp);  if (pp instanceof MergedBeanDefinitionPostProcessor) {  internalPostProcessors.add(pp);  } } sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors);  // Now, register all regular BeanPostProcessors. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String ppName : nonOrderedPostProcessorNames) {  BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);  nonOrderedPostProcessors.add(pp);  if (pp instanceof MergedBeanDefinitionPostProcessor) {  internalPostProcessors.add(pp);  } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); 复制代码

上面的这些代码都是差很少了的、都是能排序的话就先排序、而后再注册

sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); 复制代码

后面又从新注册 internalPostProcessors 里面的 BeanPostProcessor ,这个是什么操做呢,咱们看看具体的注册方法

public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
 // 先移除  this.beanPostProcessors.remove(beanPostProcessor);  if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {  this.hasInstantiationAwareBeanPostProcessors = true;  }  if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {  this.hasDestructionAwareBeanPostProcessors = true;  }  // 再增长  this.beanPostProcessors.add(beanPostProcessor); 复制代码

这么操做一波以后、原来注册的 BeanPostProcessor 的位置就会被移动到 List 的尾部了

咱们再回到咱们上面的问题,咱们的 Student 类明明实现了 BeanPostProcessor 接口,可是却没有被回调到

咱们看看对应的代码

List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {  BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);  nonOrderedPostProcessors.add(pp);  if (pp instanceof MergedBeanDefinitionPostProcessor) {  internalPostProcessors.add(pp);  } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); 复制代码
ClassPathXmlApplicationContext构造函数-->refresh()-->registerBeanPostProcessors()
复制代码

当咱们在 refresh 的时候、执行到 registerBeanPostProcessors , 咱们发现整个 Spring 管理的 BeanDefinition 集合中、只有 Student 是实现了 BeanPostProcessor 接口的、而后咱们经过 getBean 方法去获取这个 bean , 注意这个时候 AbstractBeanFactory 中的 beanPostProcessors 除了 Spring 本身加入的一些 BeanPostProcessor 以外,Student 的对象不存在于此( Student 的对象还没被 Spring 建立出来) , 而后就走 getBean 的流程,走到 doCreateBean、走到 initializeBean 而后回调 BeanPostProcessor ,可是这个时候 Student 对象仍是不在 beanPostProcessors 集合中、因此就不会打印了。其实能够得出一个结论,实现了 BeanPostProcessor 的 bean 当自身被 Spring 建立的时候、它是不会被回调到的

而上面还留了一个问题

List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); 复制代码

为啥 orderedPostProcessorNames 和 nonOrderedPostProcessorNames 的集合存放的是一个 String , 而不是直接是 BeanPostProcessor ?主要是为了在建立实现 Ordered 接口的类的时候、即实现了 PriorityOrdered 接口又实现了 BeanPostProcessor 接口的对象获得回调,同理当建立非 PriorityOrdered/Ordered 接口的 bean 时,实现了 PriorityOrdered/Ordered 的 BeanPostProcessor 也能获得回调。这也是一种优先级的关系

群聊
群聊
此次必定?
此次必定?
相关文章
相关标签/搜索