写点什么

Spring 源码学习 12:registerBeanPostProcessors

发布于: 2021 年 01 月 02 日

前言


前面通过 invokeBeanFactoryPostProcessors 这一步了解到了什么是 BeanFactoryPostProcessor ,以及 BeanFactoryPostProcessor 的使用及作用,并通过 invokeBeanFactoryPostProcessors 这一步源码,对 BeanFactoryPostProcessor 的加载流程有了进一步了解。


现在就一起进入下一个环节:


registerBeanPostProcessors(beanFactory);


这一步主要的作用是加载 BeanPostProcessor,从名字也可以看出,只是加载,并没有执行。


不过,在进入源码之前,依然是结合官网,先了解以下几个问题:


  1. 什么是 BeanPostProcessor?

  2. BeanPostProcessor 是如何使用的?

  3. BeanPostProcessor 有什么用?


什么是 BeanPostProcessor ?



如截图所示,在官网 1.8.1 Customizing Beans by Using a BeanPostProcessor 中介绍, BeanPostProcessor 接口定义回调方法,可以实现这些方法,从而在 Bean 实例化期间修改 Bean 的属性。


BeanPostProcessor 是如何使用的?


@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor {

@Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof UserComponent) {
System.out.println("BeanPostProcessor 开始执行 初始化前..." + beanName);
UserComponent userComponent = (UserComponent) bean; userComponent.setUserName("liuzhihang-postProcessBeforeInitialization");
return userComponent;
}
return bean; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

if (bean instanceof UserComponent) {
System.out.println("BeanPostProcessor 开始执行 初始化后..." + beanName);
UserComponent userComponent = (UserComponent) bean; userComponent.setUserName("liuzhihang-postProcessAfterInitialization");
return userComponent;
}
return bean; }}
复制代码


如代码所示,只需要声明一个自己的 MyBeanPostProcessor 来实现 BeanPostProcessor 并重写其方法:


postProcessBeforeInitialization :在 Bean 实例后调用初始化方法之前进行处理。


postProcessAfterInitialization :在 Bean 实例化后调用初始化方法之后进行处理。


并且在测试时可以发现,BeanPostProcessor 修改的属性会覆盖 BeanFactoryPostProcessor,至于原因可以阅读下 Spring 源码学习 11:invokeBeanFactoryPostProcessors 这篇文章,相信对 BeanFactoryPostProcessor 有了一定的了解之后,一定会有自己的答案。


当然我个人的理解就是 BeanFactoryPostProcessor 是在 Bean 实例化之前,是通过修改元数据从而修改的 Bean 的元素信息。


这块也可以通过代码进行验证。



可以看出,执行顺序是


BeanFactoryPostProcessor#postProcessBeanFactory

->

BeanPostProcessor#postProcessBeforeInitialization

->

BeanPostProcessor#postProcessAfterInitialization


所以,后面修改的属性,会覆盖之前修改的属性。


至于 BeanPostProcessor 是如何修改属性的,在这里先不做介绍,继续进入本节的主角 registerBeanPostProcessors 源码分析


registerBeanPostProcessors 源码


在 Spring refresh 方法中,执行 registerBeanPostProcessors 主要作用是将 BeanPostProcessor 注册到容器中,源码如下:


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


这里调用了 PostProcessorRegistrationDelegate 类的静态方法,继续跟进:


public static void registerBeanPostProcessors(        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 查找 BeanPostProcessor 类型的 Bean 的名称集合, 就是获取所有继承了 BeanPostProcessor 的类 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. // 注册一个 BeanPostProcessorChecker,用来记录 bean 在 BeanPostProcessor 实例化时的信息。 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered, // Ordered, and the rest. // 四个集合 区分实现不同接口的 BeanPostProcessors List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); 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. // 排序后执行 实现 PriorityOrdered 的 BeanPostProcessors sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered. 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);
// Finally, re-register all internal BeanPostProcessors. 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). beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));}
复制代码


代码中添加了相应的注释,相信读过上一篇文章(invokeBeanFactoryPostProcessors 源码)的小伙伴,一定会感觉非常熟悉,这个方法的逻辑和上面基本一致,都是声明集合,排序,注册到 BeanFactory 中。


不过还是有区别的:


registerBeanPostProcessors 这一步仅仅将 BeanPostProcessor 注册到 BeanFactory 中,并没有执行!!!


总结


本文源码部分相对比较简单,主要花费部分篇幅介绍什么是 BeanPostProcessor 以及 BeanPostProcessor 的使用方法。


一句话总结这一步就是:注册 BeanPostProcessor 到 BeanFactory 中,但是没有执行。



相关推荐



发布于: 2021 年 01 月 02 日阅读数: 44
用户头像

个人公众号:『 程序员小航 』 2020.07.30 加入

某不知名互联网公司 Java 程序员一枚。记录工作学习中的技术、开发及源码笔记;分享生活中的见闻感悟。

评论

发布
暂无评论
Spring 源码学习 12:registerBeanPostProcessors