BeanFactory后置处理器

接 springIOC - ConfigurationClassPostProcessor - full / lite  

代码块:

org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

do {
    parser.parse(candidates);
    parser.validate();
    //map.keyset
    Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
    configClasses.removeAll(alreadyParsed);

    // Read the model and create bean definitions based on its content
    if (this.reader == null) {
        this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
    }

    /**
     * 这里值得注意的是扫描出来的bean当中可能包含了特殊类
     * 比如ImportBeanDefinitionRegistrar那么也在这个方法里面处理
     * 但是并不是包含在configClasses当中
     * configClasses当中主要包含的是importSelector
     * 因为ImportBeanDefinitionRegistrar在扫描出来的时候已经被添加到一个list当中去了
     */

    //将 bd 放到 map 中
    this.reader.loadBeanDefinitions(configClasses);
    alreadyParsed.addAll(configClasses);

    candidates.clear();
    //由于我们这里进行了扫描,把扫描出来的BeanDefinition注册给了factory
    //但是
    if (registry.getBeanDefinitionCount() > candidateNames.length) {
        String[] newCandidateNames = registry.getBeanDefinitionNames();
        Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
        Set<String> alreadyParsedClasses = new HashSet<>();
        for (ConfigurationClass configurationClass : alreadyParsed) {
            alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
        }
        for (String candidateName : newCandidateNames) {
            if (!oldCandidateNames.contains(candidateName)) {
                BeanDefinition bd = registry.getBeanDefinition(candidateName);
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                        !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                    candidates.add(new BeanDefinitionHolder(bd, candidateName));
                }
            }
        }
        candidateNames = newCandidateNames;
    }
}
while (!candidates.isEmpty());

parse 解析完后, 就会调用 loadBeanDefinitions方法.

这方法会将 StartConfig.java 解析出来的一些 bd, 注册到spring容器中.

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    for (ConfigurationClass configClass : configurationModel) {
        loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}

这个方法里面, 就会对配置文件中的 @Bean 进行注册,

然后会调用 前面解析到的 ImportBeanDefinitionRegistrar.registerBeanDefinitions 方法. 

private void loadBeanDefinitionsForConfigurationClass(
        ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

    if (trackedConditionEvaluator.shouldSkip(configClass)) {
        String beanName = configClass.getBeanName();
        if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
            this.registry.removeBeanDefinition(beanName);
        }
        this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
        return;
    }

    // 注册 @Import 导入的普通 bean , 或者 ImportSelector 导入的普通bean
    if (configClass.isImported()) {
        registerBeanDefinitionForImportedConfigurationClass(configClass);
    }
    //@Bean 的注册
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
        loadBeanDefinitionsForBeanMethod(beanMethod);
    }

     //xml
    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

    //注册Registrar
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

这里需要特别注意一下 loadBeanDefinitionsForBeanMethod

他是对 @Bean 进行注册的, 有一段代码比较重要

ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource());
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

//如果 method 是静态的
if (metadata.isStatic()) {
    // static @Bean method 
   // static时, 设置的是 BeanClassName 属性
beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(methodName); } else { //非static的 method, 设置了一个 FactoryBeanName 属性 // instance @Bean method beanDef.setFactoryBeanName(configClass.getBeanName()); beanDef.setUniqueFactoryMethodName(methodName); } beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);

这里配置了构造函数自动注入模式

实例代码:

@Configuration
public class AppConfig {

    @Bean
    public static A a(){
        return new A();
    }

    @Bean
    public B b(){
        a();
        return  new B();
    }
}

这里对 A 和 B 都进行了解析, 转化成了 ConfigurationClassBeanDefinition 

1.静态方法时, 设置的

BeanClassName = "xxx.xxx.xxx.AppConfig"

FactoryMethodName = "a"

创建的时候, 会来找 AppConfig的a()

2.非静态方法时, 设置的

FactoryBeanName = "xxx.xxx.xxx.AppConfig"

UniqueFactoryMethodName = "b"

创建 b 的时候, 会来这里找 b() 方法

原文地址:https://www.cnblogs.com/elvinle/p/13245884.html