Spring的BeanDefinitionRegistryPostProcessor接口详解

BeanDefinitionRegistryPostProcessor介绍

BeanDefinitionRegistryPostProcessor 它是Spring框架的一个扩展点,用于对Bean定义的注册过程进行干预和定制,例如添加,修改或删除Bean定义等

BeanDefinitionRegistryPostProcessor 它继承BeanFactoryPostProcessor接口,并在其基础上扩展了一个新的方法,即:postProcessBeanDefinitionRegistry()方法。

BeanFactoryPostProcessor源码:

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

BeanDefinitionRegistryPostProcessor源码:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

Spring容器初始化时,从资源中读取到bean的相关定义后,保存在beanDefinitionMap,实例化bean的操作就是依据这些bean的定义来做的,而在实例化之前,Spring允许我们通过自定义扩展来改变bean的定义,定义一旦变了,后面的实例也就变了,而beanFactory后置处理器,即BeanFactoryPostProcessor就是用来改变bean定义的。

BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口,BeanFactoryPostProcessor的实现类在其postProcessBeanFactory方法被调用时,可以对bean的定义进行控制,因此BeanDefinitionRegistryPostProcessor的实现类一共要实现以下两个方法:

  • void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException:该方法的实现中,主要用来对bean定义做一些改变。
  • void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException:该方法用来注册更多的bean到spring容器中,详细观察入参BeanDefinitionRegistry接口,看看这个参数能带给我们什么能力。

从BeanDefinitionRegistry可以看到,BeanDefinitionRegistry提供了丰富的方法来操作BeanDefinition,判断、注册、移除等方法都准备好了,我们在编写postProcessBeanDefinitionRegistry方法的内容时,就能直接使用入参registry的这些方法来完成判断和注册、移除等操作。

BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的区别

BeanFactoryPostProcessor可以修改各个注册的Bean,BeanDefinitionRegistryPostProcessor可以动态将Bean注册。

BeanDefinitionRegistryPostProcessor的执行时机

postProcessBeanDefinitionRegistry执行时机

  • AbstractApplicationContext#refresh

  • PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

优先执行实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,其次就是实现了接口Ordered的,最后才是两者都没有的。

调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法。

postProcessBeanFactory执行时机

跟BeanDefinitionRegistryPostProcessor的调用路径一样,在调用了所有的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法后,紧接着就会处理所有的BeanFactoryPostProcessor,按优先级调用其postProcessBeanFactory接口。

源码-来自:PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

优先执行实现了PriorityOrdered接口的BeanFactoryPostProcessor,其次就是实现了接口Ordered的,最后才是两者都没有的。

重要实现类

ConfigurationClassPostProcessor

Spring中的BeanDefinitionRegistryPostProcessor的实现类ConfigurationClassPostProcessor,通过这个类会将Spring中@Configuration、@Import、@Bean等注解的类扫描出来,并封装成BeanDefinition注册进容器中。

后置处理器ConfigurationClassPostProcessor如何解析注解

自定义实现方式

  • 在postProcessBeanDefinitionRegistry()方法被调用的时候手工在Spring中注册了Student类的BeanDefinition信息;
  • 在postProcessBeanFactory()方法被调用的时候,从Spring容器中取出Dog类的BeanDefinition信息和Student类的实例;
@Data
public class Student{
    private String name;
    private String age;
}
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //手工定义一个beanDefinition实例
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        //给beanDefinition填充属性
        beanDefinition.setBeanClass(Student.class);
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        PropertyValue propertyValue1 = new PropertyValue("name", "张三");
        PropertyValue propertyValue2 = new PropertyValue("age", "11");
        propertyValues.addPropertyValue(propertyValue1);
        propertyValues.addPropertyValue(propertyValue2);
        beanDefinition.setPropertyValues(propertyValues);
        //注册手工定义的beanDefinition
        registry.registerBeanDefinition("student", beanDefinition);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("-----------postProcessBeanFactory start------------");
        //根据类名取出手工注册的beanDefinition
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("student");
        System.out.println(beanDefinition.getBeanClassName());
        //根据类从容器中取出手工注册的beanDefinition所描述的实例bean
        Student student = beanFactory.getBean(Student.class);
        System.out.println(student.getName());
        System.out.println(student.getAge());
        System.out.println("-----------postProcessBeanFactory end------------");
    }

 

posted @ 2023-12-23 11:40  残城碎梦  阅读(549)  评论(0编辑  收藏  举报