在此系列文章中,我总结了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的更多相关文章

  1. 0001 - Spring 框架和 Tomcat 容器扩展接口揭秘

    前言 在 Spring 框架中,每个应用程序上下文(ApplicationContext)管理着一个 BeanFactory,BeanFactory 主要负责 Bean 定义的保存.Bean 的创建. ...

  2. Spring8:一些常用的Spring Bean扩展接口

    前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...

  3. 深入理解Spring系列之八:常用的扩展接口

    转载 https://mp.weixin.qq.com/s/XfhZltSlTall8wKwV_7fKg Spring不仅提供了一个进行快速开发的基础框架,而且还提供了很多可扩展的接口,用于满足一些额 ...

  4. spring初始化源码浅析之关键类和扩展接口

    目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...

  5. spring扩展点整理

    本文转载自spring扩展点整理 背景 Spring的强大和灵活性不用再强调了.而灵活性就是通过一系列的扩展点来实现的,这些扩展点给应用程序提供了参与Spring容器创建的过程,好多定制化的东西都需要 ...

  6. spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  7. spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入

    <spring扩展点之二:spring中关于bean初始化.销毁等使用汇总,ApplicationContextAware将ApplicationContext注入> <spring ...

  8. PHP安装memcache扩展接口步骤

    1.将php_memcache.dll文件保存到php的应用程序扩展ext目录中 2.在php.ini配置文件添加扩展的位置,加入一行extension=php_memcache.dll 3.重新启动 ...

  9. hibernate核心接口,和扩展接口。回顾笔记,以前没记,现在补上,纯手工敲的。

    hibernate核心接口: 所有的hibernate应用都会访问hibernate的5个核心接口 1,Configuration接口 Configuration用于配置并且根启动Hibernate. ...

  10. Java开发笔记(五十九)Java8之后的扩展接口

    前面介绍了接口的基本用法,有心的朋友可能注意到这么一句话“在Java8以前,接口内部的所有方法都必须是抽象方法”,如此说来,在Java8之后,接口的内部方法也可能不是抽象方法了吗?之所以Java8对接 ...

随机推荐

  1. 花朵识别系统Python+TensorFlow+Django+卷积神经网络算法实现

    一.背景 花朵识别系统,基于Python实现,深度学习卷积神经网络,通过TensorFlow搭建卷积神经网络算法模型,并对数据集进行训练最后得到训练好的模型文件,并基于Django搭建可视化操作平台. ...

  2. React后台管理系统10 菜单数据的整理、以及其余路径的配置、刷新时默认当前选中样式

    对菜单进行数据整理 import { DesktopOutlined, FileOutlined, PieChartOutlined, TeamOutlined, UserOutlined, } fr ...

  3. 【翻译】rocksdb write stall

    翻译自官方wiki:https://github.com/facebook/rocksdb/wiki/Write-Stalls 转载请注明出处:https://www.cnblogs.com/morn ...

  4. 【C#/.NET】使用Automapper映射record类型

    ​ 当使用Automapper进行对象映射时,通常我们会使用POCO(Plain Old CLR Object)类作为源对象和目标对象.然而,自从C# 9引入了record类型,它们提供了更简洁.不可 ...

  5. SpringBoot 多环境切换

    日常开发中一般都会有三个不同的环境,分别是开发环境(dev),测试环境(test)和生产环境(prod),不同的环境各种配置都不相同,比如数据库配置,服务器端口等等. Spring Boot 多环境配 ...

  6. 筛选出N以内的素数

    解题思路:1.素数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数.(也就是只有 1 和它本身能整除)2.利用两个for循环来判断素数. 注意事项:1.注意for添加花括号.2.注意输 ...

  7. 巧用 awk 批量杀进程

    今天遇到线上的一个问题: 我需要批量杀死某台机器的 PHP 进程,该怎么办? 注意,不是 php-fpm,是常驻任务. 如果是一个进程,那就好办了,ps -ef | grep php,找到 PID 然 ...

  8. React: 按钮点击时修改颜色

    背景 当存在多个点击按钮时,需要提示用户点击的哪个按钮,所以要进行颜色的修改 import * as React from 'react'; import './style.css'; export ...

  9. 解决AccessDatabaseEngine.exe 32位64位安装失败问题

    cmd下执行 你的路径\AccessDatabaseEngine.exe /quiet 转载于:https://www.cnblogs.com/64mb/p/10844676.html

  10. 利用选项卡提高Visual Studio 2022开发效率

    设计器作为软件开发的必要工具,其效率的提高显得尤为重要.Visual Studio 2022作为一款功能强大的设计器,通过选项卡提高了工作效率,让开发者在使用过程中更加便捷. 在Visual Stud ...