架构のSpring扩展点(二):Bean定义操作-​BeanDefinitionRegistryPostProcessor

40 阅读4分钟

 🍅 作者简介:齐大,自学Java入门,现在某国企担任初级架构师

🍅 有自己独立的学习方法,以及适合大部分人的学习路线,面试架构思路等

🍅 关注公众号【齐疾行者Code】,查看最新最全的知识分享

Spring 的扩展点 是Spring易扩展的一个重要体现,熟悉这些扩展点的定义方式,以及其调用时机,不仅成为工作中利器,也能深度理解Spring框架的切入点。

BeanDefinitionRegistryPostProcessor接口的扩展点

BeanDefinitionRegistryPostProcessor用于对Bean定义的注册过程进行干预和定制。继承BeanFactoryPostProcessor接口,并在其基础上扩展了一个新的方法,即:postProcessBeanDefinitionRegistry()方法。

它提供了一种机制,允许开发人员在Bean定义注册之前和之后对Bean定义进行自定义处理。

图片

编辑

来源

org.springframework.beans它是由Spring本身提供的容器级别的接口。

注:Bean定义与Bean实例化是不一样的

Bean定义:

Spring容器初始化时,从资源中读取到bean的相关定义后,保存在BeanDefinitionMap,这是将Spring管理的类封装为 BeanDefinition对象。

Bean实例化:

Spring通过扩展接口对BeanDefinition操作完成后,创建代理类的过程,是基于BeanDefinitionMap中的数据进行的

//所有Bean定义加载完成之后,Bean实例化之前被调用
//用来注册更多的bean到spring容器中
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;

//继承自BeanFactoryPostProcessor接口的方法,用于在BeanFactory完成实例化之后对BeanFactory进行后置处理
//用来改变bean定义的
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;

Spring内置实现类

  • PropertyResourceConfigurer
    
    它抽象了容器BeanFactory后置处理阶段对容器中所有bean定义中的属性进行配置的一般逻辑,属性配置所使用的属性来源是基类PropertiesLoaderSupport方法所规定的那些属性。
    
    public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport
        implements BeanFactoryPostProcessor, PriorityOrdered {
    
      @Override
      public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
          // 合并本地属性和外部指定的属性文件资源中的属性 
          Properties mergedProps = mergeProperties();
    
          // 将属性的值做转换(仅在必要的时候做) 
          convertProperties(mergedProps);
    
          // 对容器中的每个bean定义进行处理,也就是替换每个bean定义中的属性中的占位符  
          processProperties(beanFactory, mergedProps);
        }
        catch (IOException ex) {
          throw new BeanInitializationException("Could not load properties", ex);
        }
      }
    

  • CustomAutowireConfigurer
    
    它允许您注册自己的自定义限定符(Qualifer)注解类型,即使它们没有使用Spring的@Qualifier注解进行注解。
    
    public class CustomAutowireConfigurer implements BeanFactoryPostProcessor, BeanClassLoaderAware, Ordered {
    
      ........
    
      @Override
      @SuppressWarnings("unchecked")
      public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (this.customQualifierTypes != null) {
          if (!(beanFactory instanceof DefaultListableBeanFactory)) {
            throw new IllegalStateException(
                "CustomAutowireConfigurer needs to operate on a DefaultListableBeanFactory");
          }
          DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
          if (!(dlbf.getAutowireCandidateResolver() instanceof QualifierAnnotationAutowireCandidateResolver)) {
            dlbf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
          }
          QualifierAnnotationAutowireCandidateResolver resolver =
              (QualifierAnnotationAutowireCandidateResolver) dlbf.getAutowireCandidateResolver();
          for (Object value : this.customQualifierTypes) {
            Class<? extends Annotation> customType = null;
            if (value instanceof Class) {
              customType = (Class<? extends Annotation>) value;
            }
            else if (value instanceof String) {
              String className = (String) value;
              customType = (Class<? extends Annotation>) ClassUtils.resolveClassName(className, this.beanClassLoader);
            }
            else {
              throw new IllegalArgumentException(
                  "Invalid value [" + value + "] for custom qualifier type: needs to be Class or String.");
            }
            if (!Annotation.class.isAssignableFrom(customType)) {
              throw new IllegalArgumentException(
                  "Qualifier type [" + customType.getName() + "] needs to be annotation type");
            }
            resolver.addQualifierType(customType);
          }
        }
      }
    }
    

自定义实现方式

MyBeanDefinitionRegistryPostProcessor

  • 在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------------");
        }
    

初始化和执行时机

  1. 执行项目的主类org.springframework.boot.SpringApplication#run被调用;

  2. 执行到org.springframework.boot.SpringApplication#refreshContext,开始容器刷新,进入了核心调用链;

  3. org.springframework.context.support.AbstractApplicationContext#refresh方法中进行容器刷新;

  4. org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors的方法中

    开始初始化和执行实现BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry()和postProcessBeanFactory();

  5. AbstractApplicationContext#invokeBeanFactoryPostProcessors的方法执行     org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors();

  6. 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中,并不是直接就初始化和执行postProcessBeanDefinitionRegistry()和postProcessBeanFactory(),而是又进行了一系列的判断,其判断顺序是:

    (1):通过AbstractApplicationContext#addBeanFactoryPostProcessor提前注册的BeanDefinitionRegistryPostProcessor实现类

    (2):实现了PriorityOrdered接口;

    (3): 是否实现了Ordered;

    (4): 剩下的其他BeanDefinitionRegistryPostProcessor实现类;

  7. 在执行完自定义的方法postProcessBeanDefinitionRegistry后,紧接着就开始执行

    MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory方法了

关注公众号齐疾行者Code获取更新更全的架构知识

架构のSpring扩展点(一):上下文创建前的动态处理-ApplicationContextInitializer

架构のSpring扩展点(二):Bean定义操作-BeanDefinitionRegistryPostProcessor

架构のSpring扩展点(三):Bean生命周期操作-InstantiationAwareBeanPostProcessor

架构のSpring扩展点(四):Bean初始化时对象自动注入-Aware全解析

架构のSpring扩展点(五):如何保证在同一线程内获取的bean是同一对象-自定义Scope

架构のSpring扩展点(六):ApplicationContextAwareProcessor接口全解析,看完就懂

架构のSpring扩展点(七):Java自带注解@postcontruct全解析,为什么不推荐使用?那什么时候可以使用了

认知结构的提升,需要合适的思考方法-架构提升