首页 > 其他分享 >Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

时间:2023-10-10 10:48:28浏览次数:39  
标签:Spring 接口 springframework BeanDefinitionRegistryPostProcessor import org user

在此系列文章中,我总结了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,接口,springframework,BeanDefinitionRegistryPostProcessor,import,org,user
From: https://www.cnblogs.com/myshare/p/17754010.html

相关文章

  • 多个接口同时调用同一个方法
    如果多个接口同时调用同一个方法,会增加该方法的负载和并发量。这可能会导致性能问题,特别是当方法需要执行大量计算或涉及到I/O操作时。为了避免性能问题,可以采取以下措施:缓存结果:对于一些计算结果比较稳定的方法,可以将结果缓存起来,避免重复计算。异步执行:对于一些需要进行I......
  • SpringBoot整合XXLJob
    目录XXLJob简介特性模块安装调度中心初始化数据库配置启动整合执行器pomymlXxlJobConfig启动执行器实践简单的定时任务在执行器创建任务在调度中心创建执行器在调度中心创建任务带前置和后置处理的定时任务XxlJob注解详解创建带前(后)置处理的任务父子任务父子执行器关联父子任务执......
  • idea系列---【上一次打开springboot项目还好好的,现在打开突然无法启动了】
    问题昨天走的时候项目还能正常启动,今天来了之后突然报下面的错误:Error:Kotlin:ModulewascompiledwithanincompatibleversionofKotlin.Thebinaryversionofitsmetadatais1.7.1,expectedversionis1.1.16.解决方案点击idea:Build>RebuildProject重新......
  • SpringBoot集成WebSocket讲解
    目录1WebSocket1.1简介1.2WebSocket作用和调用1.2.1作用1.2.2js端调用1.3Javax1.3.1服务端1.3.1.1服务端接收1.3.1.2服务端集成1.3.1.3ping和pong消息1.3.2客户端1.3.2.1客户端接收1.3.2.2客户端发送1.4WebMVC1.4.1服务端1.1.4.1服务端接收1.1.4.2服务端集成1.1......
  • SpringBoot之实现Web消息实时消息推送
    目录1实时消息推送1.1消息推送1.2准备sql1.3短轮询1.4长轮询1.4.1简介1.4.2代码示例1.5iframe流1.6SSE1.6.1简介1.6.2与WebSocket区别1.6.3代码示例1.7MQTT1.7.1简介1.7.2为什么要用MQTT协议1.8WebSocket1实时消息推送1.1消息推送推送的场景比较多,比如有......
  • Spring Boot 访问静态资源css/js
    一、前言我们用SpringBoot搭建Web应用时(如搭建一个博客),经常需要在Html中访问一些静态资源,比如:css样式;js脚本;favicon.ico图标等;而在SpringBoot中如果没有做任何配置,是无法直接访问静态资源的,通常会报404错误二、SpringBoot访问静态资源的默认目录Spring......
  • SpringBootWeb案例-2上
    SpringBootWeb案例前面我们已经实现了员工信息的条件分页查询以及删除操作。关于员工管理的功能,还有两个需要实现:新增员工修改员工首先我们先完成"新增员工"的功能开发,再完成"修改员工"的功能开发。而在"新增员工"中,需要添加头像,而头像需要用到"文件上传"技术。当整个员工管理功......
  • python接口自动化之request请求,如何使用 Python调用 API?
    Python实战|如何使用Python调用API一、HTTP 请求HTTP 请求是在 HTTP 协议下的一种数据格式,用于向服务器发送请求,其通常由请求行、请求头和请求体三部分构成,请求头和请求体之间用空行隔开,其中各部分包含的信息如下:请求行 (Request Line):包括请求方法 (GET请求、POST请......
  • Spring源码解析——ApplicationContext容器refresh过程
    正文在之前的博文中我们一直以BeanFactory接口以及它的默认实现类XmlBeanFactory为例进行分析,但是Spring中还提供了另一个接口ApplicationContext,用于扩展BeanFactory中现有的功能。ApplicationContext和BeanFactory两者都是用于加载Bean的,但是相比之下,ApplicationContext提供了......
  • 查询学霸积分榜的接口声明
        ......