Spring注解驱动之BeanDefinitionRegistryPostProcessor原理解析
作者:融极 发布时间:2023-11-24 23:24:21
BeanDefinitionRegistryPostProcessor概述
可以看到BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口。
注释中说执行时机是所有合法的bean定义已经加载,但是还没实例化。
看起来和BeanFactoryPostProcessor执行时机差不多,但是BeanFactoryPostProcessor的注释是所有bean定义被加载,而BeanDefinitionRegistryPostProcessor是所有合法的bean定义。
接着看注释:
This allows for adding further bean definitions before the next post-processing phase kicks in.
意思是BeanDefinitionRegistryPostProcessor允许添加将来的bean定义在下一个后置处理器阶段开始之前。简单说就是还可以往容器中增加新的bean的定义。
因此,大概率BeanDefinitionRegistryPostProcessor的执行顺序在BeanFactoryPostProcessor之前。
案例实践
首先,编写一个类,例如MyBeanDefinitionRegistryPostProcessor,它应要实现BeanDefinitionRegistryPostProcessor这个接口。
package com.meimeixia.ext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;
import com.meimeixia.bean.Blue;
// 记住,我们这个组件写完之后,一定别忘了给它加在容器中
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// TODO Auto-generated method stub
System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:" + beanFactory.getBeanDefinitionCount());
}
/**
* 这个BeanDefinitionRegistry就是Bean定义信息的保存中心,这个注册中心里面存储了所有的bean定义信息,
* 以后,BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息来创建bean实例的。
*
* bean定义信息包括有哪些呢?有这些,这个bean是单例的还是多例的、bean的类型是什么以及bean的id是什么。
* 也就是说,这些信息都是存在BeanDefinitionRegistry里面的。
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessBeanDefinitionRegistry...bean的数量:" + registry.getBeanDefinitionCount());
// 除了查看bean的数量之外,我们还可以给容器里面注册一些bean,我们以前也简单地用过
/*
* 第一个参数:我们将要给容器中注册的bean的名字
* 第二个参数:BeanDefinition对象
*/
// RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class); // 现在我准备给容器中添加一个Blue对象
// 咱们也可以用另外一种办法,即使用BeanDefinitionBuilder这个构建器生成一个BeanDefinition对象,很显然,这两种方法的效果都是一样的
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
registry.registerBeanDefinition("hello", beanDefinition);
}
}
测试结果
可以看到,BeanDefinitionRegistryPostProcessor里面的两个方法,postProcessBeanDefinitionRegistry在postProcessBeanFactory之前执行。
BeanDefinitionRegistryPostProcessor比BeanFactoryPostProcessor先执行。
源码分析
自己在测试示例中方法打断点,然后查看调用栈即可,下面是一些主要的代码片段。
继续向下看,可以看到会取出所有实现了BeanDefinitionRegistryPostProcessor接口的类,即从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件。
然后,优先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor组件。
点进去这个方法里面一看究竟,原来是先调用完BeanDefinitionRegistryPostProcessor组件里面的postProcessBeanDefinitionRegistry方法,然后再来调用它里面的postProcessBeanFactory方法。
我们再来仔细看一下PostProcessorRegistrationDelegate类中的invokeBeanFactoryPostProcessors方法,只不过这时是从程序停留的地方(即第122行代码处)往下看,如下图所示。
小结
BeanDefinitionRegistryPostProcessor的执行流程。
1. 创建IOC容器。
2. 调用refresh方法。
3. 从IOC容器中获取所有的BeanDefinitionRegistryPostProcessor组件,并依次触发它们的postProcessBeanDefinitionRegistry方法,之后触发它的postProcessBeanFactory方法。
4. 从IOC容器中获取到所有的BeanFactoryPostProcessor组件,并依次触发它们的postProcessBeanFactory方法。
来源:https://blog.csdn.net/tianzhonghaoqing/article/details/126918816
猜你喜欢
- package dao;import java.sql.*;public class BaseDao { //oracle//&n
- 1)首先启动hadoop2个进程,进入hadoop/sbin目录下,依次启动如下命令[root@node02 sbin]# pwd/usr/
- ObjectMapper 忽略字段大小写核心代码:ObjectMapper mapper = new ObjectMapper();mapp
- 一、原理1、不变模式(不可变对象)在并行软件开发过程中,同步操作似乎是必不可少的。当多线程对同一个对象进行读写操作时,为了保证对象数据的一致
- 一、什么是命令模式命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请 求排队或者记录
- 前言Kotlin一个强大之处就在于它的扩展函数,巧妙的运用这些扩展函数可以让你写出的代码更加优雅,阅读起来更加流畅,下面总结了在开发中经常用
- 一、什么是SFTP?SFTP是一个安全文件传送协议,可以为传输文件提供一种安全的加密方法。SFTP 为 SSH的一部份,是一种传输文件到服务
- 一、常量用final修饰(也称最终变量)常量在声明时必须赋初值,赋值后不能再修改值常量名通常用全大写字母表示声明时需要添加final或sta
- 一、背景Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE
- instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:boolean result = o
- mkdir函数用于创建目录。格式如下:#include<sys/types.h>#include<sys/stat.h&g
- Java泛型是JDK 5引入的一个特性,它允许我们定义类和接口的时候使用参数类型,泛型在集合框架中被广泛使用。类型擦除是泛型中最让人困惑的部
- Java常用API介绍API概念什么是API?API(Application Programming interface) 应用程序编程接口
- 为什么要重复造轮子你可能会问,Spring已经自带了全局异常拦截,为什么还要重复造轮子呢?这是个好问题,我觉得有以下几个原因装逼Spring
- 本文实例为大家分享了MapReduce实现决策树算法的具体代码,供大家参考,具体内容如下首先,基于C45决策树算法实现对应的Mapper算子
- Java 方法执行时的动态分派和静态分派是 Java 实现多态的本质背景Java 的动态分派和静态分派也是 Java 方法的执行原理。 Ja
- Java基于对象流实现银行系统的具体代码,供大家参考,具体内容如下系统特点:数据持久化到文件中,系统启动后,加载文件中数据到集合中,相当于做
- maven配置项目的jdk版本无效排查最近在配置项目的jdk的时候发现在pom.xml中配置的1.8版本无效,maven更新后就变成了1.7
- 走马灯是一种常见的效果,本文讲一下如何用 PageView 在 Flutter 里实现一个走马灯, 效果如下,当前页面的高度比其它页面高,切
- 效果图如下所示: 1、在Adapter中加入如下代码<pre style="background-color:#2