11.ConfigurationClassPostProcessor源码

129 阅读6分钟

ConfigurationClassPostProcessor注册时机

首先在AnnotatedBeanDefinitionReader的构造函数中注册

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        /*
        这里很重要 因为ConfigurationClassPostProcessor就是在这里被注入的!
        注册了5个
        
        //BeanFactoryPostProcessor
        RootBeanDefinition def = new 
                        RootBeanDefinition(ConfigurationClassPostProcessor.class);
        //BeanPostProcessor
        RootBeanDefinition def = new 
                        RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        //BeanPostProcessor
        RootBeanDefinition def = new 
                        RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        //EventListenerMethodProcessor
        RootBeanDefinition def = new 
                        RootBeanDefinition(EventListenerMethodProcessor.class);
        RootBeanDefinition def = new 
                        RootBeanDefinition(DefaultEventListenerFactory.class);
        */
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

就是注册默认的后置处理器,这个方法跟到底,一直到registerAnnotationConfigProcessors这个方法,这个方法里面就是真正的注册各种内置的后置处理器。

其次在ClassPathBeanDefinitionScanner#scan方法中也做了判断并进行了注册。

/**
     * 扫描给定的包路径,生成BeanDefinition并注册到注册器
     */
    public int scan(String... basePackages) {
        ////获取注册器中已注册的bean数量
        int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
        //通过doScan给定包路径并生成BeanDefinition注册到registry中
        doScan(basePackages);
        // Register annotation config processors, if necessary.
        if (this.includeAnnotationConfig) {
            //  这个方法很重要 注册了内置的ConfigurationClassPostProcessor
            AnnotationConfigUtils.
                        registerAnnotationConfigProcessors(this.registry);
        }
        //返回本次扫描并注册到IOC容器中的类
        return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
    }

ConfigurationClassPostProcessor源码

在本专题博客(五)中讲解了BeanFactoryPostProcessor及子类BeanDefinitionRegistryPostProcessor,我们讲过spring初始化过程中会默认注册几个后置处理器,在refresh()正式启动spring容器过程中会调用默认注册的后置处理器。

其中有一个后置处理器叫ConfigurationClassPostProcessor

在sping中扮演着最最最重要的角色,本篇博文我们详细讲解该后置处理器。

自定义的Bean通过配置类被扫描

package tyrant;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class User {

    @Bean
    public User getUser() {
        return new User();
    }

    private int age = 31;

    private String name = "user";

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package tyrant;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
//包扫描
@ComponentScan("tyrant")
//使用xml文件启动
//@ImportResource("applicationContext.xml")
public class Config {
}
public class Test {
    public static void main(String[] args) {
        
       //第一种方式 如果没有参数Config.class那么Spring在扫描的时候不会扫描到我们自定义的bean
       // AnnotationConfigApplicationContext context = new     
       //                    AnnotationConfigApplicationContext(Config.class);  
                                                
       //第二种方式 
        AnnotationConfigApplicationContext context = new        
                                             AnnotationConfigApplicationContext();
        //注册配置类
        //如果没有下面这句代码 那么Spring在扫描的时候不会扫描到我们自定义的bean
        context.register(Config.class);
        
        context.refresh();
        BeanDefinition beanDefinition =  context.getBeanDefinition("getUser");
        //查看spring给我生成的具体BeanDefinition类型
        //ConfigurationClassBeanDefinition
        System.out.println(beanDefinition.getClass().getSimpleName());
    }
}

image.png

ConfigurationClassPostProcessor作用

ConfigurationClassPostProcessor是一个BeanFactory的后置处理器。因此它的主要功能是参与BeanFactory的建造,在这个类中,会解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解。

ConfigurationClassPostProcessor注册时机

首先在AnnotatedBeanDefinitionReader的构造函数中会被注册

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        /*
        这里很重要 因为ConfigurationClassPostProcessor就是在这里被注入的!
        注册了5个
        
        BeanFactoryPostProcessor
        RootBeanDefinition def = new 
                        RootBeanDefinition(ConfigurationClassPostProcessor.class);
        BeanPostProcessor
        RootBeanDefinition def = new 
                        RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        BeanPostProcessor
        RootBeanDefinition def = new 
                        RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        EventListenerMethodProcessor
        RootBeanDefinition def = new 
                        RootBeanDefinition(EventListenerMethodProcessor.class);
        RootBeanDefinition def = new 
                        RootBeanDefinition(DefaultEventListenerFactory.class);
        */
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

这个方法就是注册默认的后置处理器。这个方法跟到底。

一直到registerAnnotationConfigProcessors这个方法,这个方法里面就是真正的注册各种内置的后置处理器。

其次在ClassPathBeanDefinitionScanner#scan方法中也做了判断并进行了注册。

    /**
     * 扫描给定的包路径并生成BeanDefinition注册到注册器
     */
    public int scan(String... basePackages) {
        //获取注册器中已注册的bean数量
        int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
        
        //通过doScan给定包路径并生成BeanDefinition注册到registry中
        doScan(basePackages);
        
        //Register annotation config processors,if necessary
        //includeAnnotationConfig 默认值是true
        if (this.includeAnnotationConfig) {
            //这个方法很重要 注册了内置的ConfigurationClassPostProcessor
            AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
        }
        
        //返回本次扫描并注册到IOC容器中的类
        return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
    }

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);和上面一样,不赘述。

ConfigurationClassPostProcessor调用时机

在完成spring的启动过程,会调用context.refresh();

根据context.refresh();找到这行代码invokeBeanFactoryPostProcessors(beanFactory)。

调用所有注册的beanFactory后置处理器,继续跟进去:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //getBeanFactoryPostProcessors获取后置处理器
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

跟进第一行代码invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

这个方法实现了spring后置处理器的调用,包括spring内置的处理器和程序员自定义的处理器。

ConfigurationClassPostProcessor调用时机。

需要在invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

往下找到下面的代码:

//查询BeanDefinitionRegistryPostProcessor的实现类
//获取到的是internalConfigurationAnnotationProcessor
//其实是一个ConfigurationClassPostProcessor

String[] postProcessorNames =
        beanFactory.getBeanNamesForType
            (BeanDefinitionRegistryPostProcessor.class, true, false);

//先放入优先级高的 
//即实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        //添加到数组中,后续进行遍历回调
        currentRegistryProcessors
            .add(beanFactory.getBean(ppName,                
                        BeanDefinitionRegistryPostProcessor.class));

        //存储BeanDefinitionRegistryPostProcessor实现类的名字
        processedBeans.add(ppName);
    }
}
//对BeanDefinitionRegistryPostProcessor设置调用顺序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//执行BeanDefinitionRegistryPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

这段代码就是完成ConfigurationClassPostProcessor后置处理器的调用!

首先,查找实现BeanDefinitionRegistryPostProcessor接口的bean,这里其实就有一个,就是ConfigurationClassPostProcessor。

然后判断是否实现了PriorityOrdered接口,ConfigurationClassPostProcessor确实实现了这个接口,然后放到集合中。

最后在invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);完成ConfigurationClassPostProcessor的调用,我们看下这个方法:

private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
        //for循环调用
        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }

没错,先调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法。 后续代码继续调用ConfigurationClassPostProcessor的postProcessBeanFactory方法。

Spring在启动过程中,最先调用的是ConfigurationClassPostProcessor后置处理器,该处理器通过以上两个方法完成扫描和注册BeanDefinition。

为什么只会找到内置的处理器?

PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List<BeanFactoryPostProcessor>)方法中,有这么一句代码。

beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

getBeanNamesForType看方法名:意思为指定类型的class找到Bean对应的Name并返回。

为什么只会找到内置的处理器ConfigurationClassPostProcessor呢?

如果我们自定义了BeanFactoryPostProcessor会被找到吗?

不会。

源码之下无秘密,直接跟进源码:

DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class\<?>, boolean, boolean)

@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
   if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
      //跟进这里
      return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
   }
   Map<Class<?>, String[]> cache =
         (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
   String[] resolvedBeanNames = cache.get(type);
   if (resolvedBeanNames != null) {
      return resolvedBeanNames;
   }
   resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
   if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
      cache.put(type, resolvedBeanNames);
   }
   return resolvedBeanNames;
}
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
   List<String> result = new ArrayList<>();
   /***
   this.beanDefinitionNames = {ArrayList@1457}  size = 8
     0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
     1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
     2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
     3 = "org.springframework.context.event.internalEventListenerProcessor"
     4 = "org.springframework.context.event.internalEventListenerFactory"
     5 = "config"
     6 = "user"
     7 = "userService
   ***/
   for (String beanName : this.beanDefinitionNames) {
    //代码略 
    
    //判断是否匹配
    boolean matchFound =
      //第一个条件
      (allowEagerInit || !isFactoryBean || (dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
      //第二个条件
      (includeNonSingletons ||(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
      //第三个条件
      isTypeMatch(beanName, type);
    
    //代码略
   }
    
    /****
   this.manualSingletonNames = {LinkedHashSet@1482}  size = 3
    0 = "environment"
    1 = "systemProperties"
    2 = "systemEnvironment"
    ****/
   for (String beanName : this.manualSingletonNames) {
     //代码略 
   }
   return StringUtils.toStringArray(result);
}

省略了部分代码。

逻辑是遍历beanDefinitionNames,matchFound标志位根据3个条件判断是否匹配。

最重要的是第三个条件:BeanDefinition对应的Class的类型和要查询的类型是否匹配。

如果匹配就返回BeanName。

ConfigurationClassPostProcessor类继承关系

ConfigurationClassPostProcessor实现了 BeanDefinitionRegistryPostProcessor接口。BeanDefinitionRegistryPostProcessor接口又继承了 BeanFactoryPostProcessor接口。

所以ConfigurationClassPostProcessor中需要重写 1.BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()方法2.BeanFactoryPostProcessor#postProcessBeanFactory() 方法。

而ConfigurationClassPostProcessor类的作用就是通过这两个方法去实现的。

image.png

ConfigurationClassPostProcessor核心方法

上文讲过,spring启动过程中

先调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry(registry)

再调用ConfigurationClassPostProcessor的postProcessBeanFactory(beanFactory)

我们来详细讨论这两个方法完成的功能。