Spring扩展接口(2):BeanDefinitionRegistryPostProcessor
在此系列文章中,我总结了Spring几乎所有的扩展接口,以及各个扩展点的使用场景。并整理出一个bean在spring中从被加载到最终初始化的所有可扩展点的顺序调用图。这样,我们也可以看到bean是如何一步步加载到spring容器中的。

BeanDefinitionRegistryPostProcessor
1、概述
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
BeanDefinitionRegistryPostProcessor为容器级后置处理器。容器级的后置处理器会在Spring容器初始化后、刷新前执行一次。还有一类为Bean级后置处理器,在每一个Bean实例化前后都会执行。
通常,BeanDefinitionRegistryPostProcessor用于在bean解析后实例化之前通过BeanDefinitionRegistry对BeanDefintion进行增删改查。
常见如mybatis的Mapper接口注入就是实现的此接口。
2、简单案例
下面是一个示例,展示了如何实现动态的给spring容器添加一个Bean:
public class User {
String name;
String password;
}
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class DynamicBeanRegistration implements BeanDefinitionRegistryPostProcessor, Ordered {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanRegistry) throws BeansException {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(User.class);
MutablePropertyValues propertyValues = new MutablePropertyValues();
PropertyValue propertyValue1 = new PropertyValue("name", "张三");
PropertyValue propertyValue2 = new PropertyValue("password", "123456");
propertyValues.addPropertyValue(propertyValue1);
propertyValues.addPropertyValue(propertyValue2);
beanDefinition.setPropertyValues(propertyValues);
beanRegistry.registerBeanDefinition("user", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("user");
System.out.println(beanDefinition.getBeanClassName());
User user = beanFactory.getBean(User.class);
System.out.println(user.getName());
System.out.println(user.getPassword());
}
@Override
public int getOrder() {
return 0;
}
}
输出:
com.sandy.springex.beanfefinitionregistrypostprocessor.User
张三
123456
- 首先定义了一个名为"User"的Java类,包含了两个属性:name和password。
- 然后定义了一个名为"DynamicBeanRegistration"的组件(通过@Component注解),实现了BeanDefinitionRegistryPostProcessor接口和Ordered接口。
- 在postProcessBeanDefinitionRegistry方法中,创建了一个RootBeanDefinition对象,并设置其beanClass为User类。接着创建了一个MutablePropertyValues对象,并通过PropertyValue对象设置了name和password属性的值。最后,将propertyValues设置到beanDefinition中,并使用beanRegistry注册了一个名为"user"的BeanDefinition。
- 在postProcessBeanFactory方法中,通过beanFactory获取了名为"user"的BeanDefinition,并输出了其beanClassName。然后使用beanFactory获取了一个User对象,并输出了其name和password属性的值。
该代码通过实现BeanDefinitionRegistryPostProcessor接口,在Spring容器启动时动态注册了一个名为"user"的Bean,并设置了其name和password属性的值。在后续的BeanFactory初始化过程中,可以通过beanFactory获取到该动态注册的Bean,并访问其属性值。
当容器中有多个BeanDefinitionRegistryPostProcessor的时候,可以通过实现Ordered接口来指定顺序:
@Override
public int getOrder() {
return 0; //值越小,优先级越高
}
3、源码分析
- 在DynamicBeanRegistration打上断点,启动SpringApplication,可以看到左下角的调用链路。

- 红框中5步都是在springboot中进行,最后super.refresh()是调用大家熟悉的spring的AbstractApplicationContext的refresh方法。

- 继续向下看


- 接下来进入核心的invokeBeanFactoryPostProcessors方法,大概逻辑是先取出所有实现了BeanDefinitionRegistryPostProcessor接口的类,然后优先调用实现了PriorityOrdered接口的组件,再调用实现了Ordered接口的组件。

- 最后,遍历调用BeanDefinitionRegistryPostProcessor组件postProcessBeanDefinitionRegistry方法

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor的更多相关文章
- 0001 - Spring 框架和 Tomcat 容器扩展接口揭秘
前言 在 Spring 框架中,每个应用程序上下文(ApplicationContext)管理着一个 BeanFactory,BeanFactory 主要负责 Bean 定义的保存.Bean 的创建. ...
- Spring8:一些常用的Spring Bean扩展接口
前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...
- 深入理解Spring系列之八:常用的扩展接口
转载 https://mp.weixin.qq.com/s/XfhZltSlTall8wKwV_7fKg Spring不仅提供了一个进行快速开发的基础框架,而且还提供了很多可扩展的接口,用于满足一些额 ...
- spring初始化源码浅析之关键类和扩展接口
目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...
- spring扩展点整理
本文转载自spring扩展点整理 背景 Spring的强大和灵活性不用再强调了.而灵活性就是通过一系列的扩展点来实现的,这些扩展点给应用程序提供了参与Spring容器创建的过程,好多定制化的东西都需要 ...
- spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情
<spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...
- spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入
<spring扩展点之二:spring中关于bean初始化.销毁等使用汇总,ApplicationContextAware将ApplicationContext注入> <spring ...
- PHP安装memcache扩展接口步骤
1.将php_memcache.dll文件保存到php的应用程序扩展ext目录中 2.在php.ini配置文件添加扩展的位置,加入一行extension=php_memcache.dll 3.重新启动 ...
- hibernate核心接口,和扩展接口。回顾笔记,以前没记,现在补上,纯手工敲的。
hibernate核心接口: 所有的hibernate应用都会访问hibernate的5个核心接口 1,Configuration接口 Configuration用于配置并且根启动Hibernate. ...
- Java开发笔记(五十九)Java8之后的扩展接口
前面介绍了接口的基本用法,有心的朋友可能注意到这么一句话“在Java8以前,接口内部的所有方法都必须是抽象方法”,如此说来,在Java8之后,接口的内部方法也可能不是抽象方法了吗?之所以Java8对接 ...
随机推荐
- SPSS统计教程:卡方检验
本文简要的介绍了卡方分布.卡方概率密度函数和卡方检验,并通过SPSS实现了一个卡方检验例子,不仅对结果进行了解释,而且还给出了卡方.自由度和渐近显著性的计算过程.本文用到的数据"2.2.sa ...
- JavaCV的摄像头实战之十二:性别检测
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<JavaCV的摄像头实战> ...
- Kali Sublist3r 报错解决办法
直接将Sublist3r.py中文件的内容替换为下面的即可 具体的更改的东西改了很多地方就不细说了,直接复制粘贴 如果遇到Error: Virustotal probably now is block ...
- 给程序员准备的“蜜糍”--SOD框架简介
注:本文是SOD框架源码仓库的首页介绍,原文地址 一.框架介绍 1,SOD框架是什么? 以前有一个著名的国产化妆品"大宝SOD密",SOD框架虽然跟它没有什么关系,但是名字的确受到 ...
- 图像处理评价指标_划分系数Vpc划分熵Vpe
划分系数划分熵 评价指标划分系数Vpc和划分熵Vpe能够反映分割矩阵的模糊程度,Vpc数值越大,分割矩阵的模糊性越小,分割效果越好:Vpe数值越小,像素分类越准确,分割效果越好. (1)划分系数Vpc ...
- Asp-Net-Core学习笔记:单元测试和集成测试
前言 我在使用 AspNetCore 的这段时间内,看了很多开源项目和博客,发现各种 .Net 体系的新技术很多人都有关注和使用,但却很少有人关注测试. 测试是软件生命周期中的一个非常重要的阶段,对于 ...
- WebSSH远程管理Linux服务器、Web终端窗口自适应(二)
上一篇:Gin+Xterm.js实现WebSSH远程Kubernetes Pod 支持用户名密码认证 支持SSH密钥认证 支持Web终端窗口自适应 支持录屏审计 Go SSH golang.org/x ...
- 【go语言】2.1.3 函数的定义和使用
在 Go 语言中,函数是一种代码抽象和复用的方式.函数可以接受参数,执行特定的操作,并返回结果. 函数的定义 函数的定义以 func 关键字开始,后面跟着函数名.参数列表.返回值列表(可选)以及函数体 ...
- 这样拆分和压缩css代码
在[拆分]和[压缩]css代码之前,首先要配置 loader 处理不同的 css 资源,因为 webpack 没有默认可处理 css 资源的规则,具体可参考这一篇 webpack处理css/less资 ...
- 文心一言 VS 讯飞星火 VS chatgpt (72)-- 算法导论7.1 3题
三.请简要地证明:在规模为 n 的子数组上,PARTITION 的时间复杂度为 Θ(n). 文心一言: 首先,我们需要明确PARTITION函数的具体定义.PARTITION函数通常用于快速排序算法中 ...