Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

spring,扩展,接口,beandefinitionregistrypostprocessor · 浏览次数 : 16

小编点评

**类和接口概述:** * **BeanDefinitionRegistryPostProcessor**:容器级后置处理器,在Spring容器初始化后、刷新前执行一次。 * **Ordered** 接口:指定组件的排序顺序。 **使用场景:** * **BeanDefinitionRegistryPostProcessor** 用于在bean解析后实例化之前通过BeanDefinitionRegistry对Bean进行增删改查。 * **BeanDefinitionRegistryPostProcessor** 常用于动态注册组件。 **可扩展点的顺序调用图:** ```mermaid graph LR BeanDefinitionRegistryPostProcessor --> BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor --> BeanDefinitionRegistry BeanDefinitionRegistryPostProcessor --> BeanDefinitionRegistry BeanDefinitionRegistryPostProcessor --> BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor --> SpringApplication AbstractApplicationContext --> invokeBeanFactoryPostProcessors invokeBeanFactoryPostProcessors --> BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry --> SpringApplication.refresh SpringApplication.refresh --> invokeBeanFactoryPostProcessors BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry --> SpringApplication.run() ``` **代码分析:** ```java public class DynamicBeanRegistration implements BeanDefinitionRegistryPostProcessor, Ordered { ... @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanRegistry) throws BeansException { ... } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { ... } } ``` **代码功能:** 1. 创建了一个名为 "User" 的根 BeanDefinition。 2. 创建了一个包含属性 "name" 和 "password" 的 `PropertyValue` 对象。 3. 将 `propertyValues` 设置到 `beanDefinition` 中。 4. 使用 `beanRegistry` 注册了一个名为 "user" 的 BeanDefinition。 5. 在 `postProcessBeanFactory` 方法中,通过 `beanFactory` 获取了名为 "user" 的 BeanDefinition,并输出了其属性值。

正文

在此系列文章中,我总结了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方法

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=31qu12pkd8qo8

与Spring扩展接口(2):BeanDefinitionRegistryPostProcessor相似的内容:

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

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

Spring扩展接口(1):ApplicationContextInitializer

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

【Spring】BeanPostProcessor后置处理器

BeanPostProcessor后置处理器是Spring提供的一个扩展点,可以在Bean初始化前后做一些事情,注意这里是bean的初始化,不是实例化,BeanPostProcessor是一个接口,里面提供了两个方法,分别为postProcessBeforeInitialization(初始化之前)

Spring缓存是如何实现的?如何扩展使其支持过期删除功能?

我们希望将这些rpc结果数据缓存起来,并在一定时间后自动删除,以实现在一定时间后获取到最新数据。类似Redis的过期时间。本文是我的调研步骤和开发过程。

Bean生命周期的扩展点:Bean Post Processor

摘要:在本篇文章中,我们将深入探讨Spring框架中的重要组件——BeanPostProcessor。首先,我们将了解其设计理念和目标,然后通过实际的例子学习如何基础使用它,如何通过BeanPostProcessor改变Bean的初始化结果以及如何利用它修改Bean的属性。 本文分享自华为云社区《S

Eureka Server 实现在线扩容

Eureka Server 实现在线扩容 作者:Grey 原文地址: 博客园:Eureka Server 实现在线扩容 CSDN:Eureka Server 实现在线扩容 需求 Eureka 是 Spring Cloud Netflix 套件中的服务注册中心组件,作为微服务的核心组件,需要支持在线扩

上周热点回顾(6.3-6.9)

热点随笔: · C#开源实用的工具类库,集成超过1000多种扩展方法 (追逐时光者)· RabbitMQ 进阶使用之延迟队列 → 订单在30分钟之内未支付则自动取消 (青石路)· .Net 中间件 - 新开源代码生成器 -ReZero (阿妮亚)· C#.Net筑基-String字符串超全总结 [深

Spring的三种依赖注入的方式

1、什么是依赖注入 依赖注入(Dependency Injection,简称DI),是IOC的一种别称,用来减少对象间的依赖关系。 提起依赖注入,就少不了IOC。 IOC(Inversion of Control,控制反转)是一种设计思想,它将原本在程序中手动创建对象的控制权,交由Spring框架来

使用 Spring 实现控制反转和依赖注入

使用 Spring 实现控制反转和依赖注入 概述 在本文中,我们将介绍IoC(控制反转)和DI(依赖注入)的概念,以及如何在Spring框架中实现它们。 什么是控制反转? 控制反转是软件工程中的一个原则,它将对象或程序的某些部分的控制权转移给容器或框架。我们最常在面向对象编程的上下文中使用它。 与传

Spring 对于事务上的应用的详细说明

1. Spring 对于事务上的应用的详细说明 @目录1. Spring 对于事务上的应用的详细说明每博一文案2. 事务概述3. 引入事务场景3.1 第一步:准备数据库表3.2 第二步:创建包结构3.3 第三步:准备对应数据库映射的 Bean 类3.4 第四步:编写持久层3.5 第五步:编写业务层3