Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

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

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor


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,可以看到左下角的调用链路。

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

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

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

  • 继续向下看

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor
Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

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

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

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

Spring扩展接口(2):BeanDefinitionRegistryPostProcessor

发表评论

评论已关闭。

相关文章

当前内容话题