[Ngbatis源码学习][SpringBoot] 由BeanFactoryPostProcessor想到
由BeanFactoryPostProcessor想到
在看Ngbatis源码时看到了对BeanFactoryPostProcessor后置处理器的使用,对其的使用并不是很了解,在此做一些学习和总结。
1. 相关类
- BeanFactoryPostProcessor
- BeanDefinitionRegistryPostProcessor
- BeanPostProcessor
2. BeanFactoryPostProcessor
2.1. 作用
BeanFactoryPostProcessor 的主要目的是在Bean实例化前对Bean的配置元数据,也就是对BeanDefinition进行修改操作。
在 Spring 中,所有的 Beans 在被完全实例化之前都是以 BeanDefinition 的形式存在的。
BeanFactoryPostProcessor 能够在Bean完全实例化之前调整和修改这些 BeanDefinition,对 BeanDefinition 的任何修改都会影响后续的 Bean 实例化和初始化过程。
2.2. 加载与执行
方式有两种:
-
利用
ConfigurableApplicationContext
接口的addBeanFactoryPostProcessor
方法。Ngbatis 的加载方式就是利用第一种,在 ApplicationContextInitializer 接口的实现类的 initialize 方法中直接调用 addBeanFactoryPostProcessor 。关于 ApplicationContextInitializer 接口的使用和原理,可以参考上一篇文章: ApplicationContextInitializer接口类的使用和原理解读。
-
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
方法中扫描实现了 BeanFactoryPostProcessor 接口的 Bean 自动加载。
BeanFactoryPostProcessor 的加载调用涉及到了十分核心的 org.springframework.context.support.AbstractApplicationContext#refresh
--> org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
方法。
第二种方式的调用实现用一张时序图来表现:
2.2.1 扩展知识
BeanFactoryPostProcessor 的加载得对 AbstractApplicationContext 的有关接口进行一个介绍。
放一张UML图在这里:
可以看到, AbstractApplicationContext 实现了 ConfigurableApplicationContext 接口,ConfigurableApplicationContext 接口又继承自 ApplicationContext,ApplicationContext 又扩展了 BeanFactory 的功能。它们之间的关系如上图。归根结底都是帮助我们在管理 Bean。
因为这里这部分不是重点内容,所以只简单说一下他们的作用与区别:
-
BeanFactory
:BeanFactory 与 ApplicationContext 存在派生关系,它是 IOC 的核心接口,虽然没有具体实现但定义了 IOC 容器最基本的规范,其他具体的容器都是通过实现 BeanFactory 的基础上,再进行功能扩展。BeanFactory 是典型的工厂模式的工厂接口。从它的方法中可以看出只提供了获取和判断的方法。
-
ApplicationContext
:在 BeanFactory 的基础上进行了功能扩展,除了间接实现了 BeanFactory 还实现了其他的接口,提供了更多面向实际应用的功能,比如国际化、监听器等。是一个更高级的容器。 -
ConfigurableApplicationContext
:ConfigurableApplicationContext 是 ApplicationContext 的子接口,它在 ApplicationContext 的基础上添加了一系列配置应用上下文的功能。里面就包括了,接下来会说的很重要的添加后置处理器的方法:addBeanFactoryPostProcessor
。 -
AbstractApplicationContext
:实现了 ConfigurableApplicationContext 接口,且通过模板方法的设计模式,实现了所有应用上下文的通用方法,其中包括了十分重要的refresh()
方法,是很重要的一个类。里面实现了包括最重要的容器初始化操作 refresh 方法、Bean 的生成和获取、监听器的添加等等。因为这个类的方法太多了,在此就不贴图了,有兴趣的小伙伴可以自行查看源码。
3. BeanDefinitionRegistryPostProcessor
3.1. 作用
BeanDefinitionRegistryPostProcessor 是 Spring 容器的一个扩展点,继承自 BeanFactoryPostProcessor,它提供了更为深入的方式来干预bean定义的注册过程。主要用于在 Spring 容器完成对 Bean 的定义信息的加载后、但在它们真正实例化之前,进行额外的操作。
它的特殊之处在于,除了能够像 BeanFactoryPostProcessor 那样修改已经注册的bean定义(BeanDefinition),还能向注册中心 BeanDefinitionRegistry 中动态地添加或移除bean定义。
可以看下 BeanDefinitionRegistryPostProcessor 的源码:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
从源码注释中可以看出来,它的执行时机是在 BeanFactoryPostProcessor 之前的阶段,对 Bean 的定义信息进行一些操作。
3.2. 加载与执行
BeanDefinitionRegistryPostProcessor 的加载与执行时序图与 BeanFactoryPostProcessor 差不多,在此基础上再加点内容就好。
从时序图中可以看到,BeanDefinitionRegistryPostProcessor 的执行在 BeanFactoryPostProcessor 之前,这也是他们的关键区别。另一个关键区别就是 BeanDefinitionRegistryPostProcessor 可以对 Bean 定义进行增删改操作,而 BeanFactoryPostProcessor 只能对 Bean 定义进行修改操作。
4. BeanPostProcessor
4.1. 作用
BeanPostProcessor
是对bean实例生效的,相对于对BeanDefinition
的处理,这个阶段更加靠后,BeanPostProcessor
处理的时候已经生成了实例对象,BeanPostProcessor
会在对象的实例基础上进行一个更进一步的加工。
BeanPostProcessor
除了能对Bean进行深加工外,还能直接进行Bean替换,Spring AOP
的功能就是这样实现的,把经过代理的Bean放了进去,替换了原有的Bean。
5. 区别与对比
三种后期处理器的执行时机用一张流程图来表示:
三种后置处理器的对比
后置处理器 | 处理目标 | 执行时机 | 主要操作 |
---|---|---|---|
BeanDefinitionRegistryPostProcessor | 针对BeanDefinitionRegistry(来自各种配置源) | 在所有BeanDefinition被加载和注册之后,在BeanFactoryPostProcessor执行之前 | 向BeanDefinitionRegistry注册、修改、删除BeanDefinition |
BeanFactoryPostProcessor | 针对BeanDefinition(Bean的配置元数据) | 在所有BeanDefinition被加载和注册之后,在Bean实例化和初始化之前 | 修改已注册的BeanDefinition,包括修改属性、改变类的定义等 |
BeanPostProcessor | 针对已经实例化,但未完全初始化的Bean对象 | 在Bean初始化过程中,具体是在Bean生命周期的初始化方法前后执行 | 主要用于在Bean初始化前后,比如修改Bean属性,生成代理对象等。 |
本文来自博客园,作者:knqiufan,转载请注明原文链接:https://www.cnblogs.com/knqiufan/p/17866312.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本