SpringBoot 刷新上下文2--执行BeanDefinitionRegistryPostProcessor

SpringBoot刷新上下文一共七篇,基于SpringBoot 2.2.7.RELEASE,Spring 5.2.6.RELEASE
SpringBoot 刷新上下文1–主流程
SpringBoot 刷新上下文2–执行BeanDefinitionRegistryPostProcessor
SpringBoot 刷新上下文3–解析引导类
SpringBoot 刷新上下文4–处理ComponentScan
SpringBoot 刷新上下文5–处理其他注解
SpringBoot 刷新上下文6–加载并注册BeanDefinition
SpringBoot 刷新上下文7–执行BeanFactoryPostProcessor

2.1、ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 处理IOC

接前篇,调用BeanDefinitionRegistryPostProcessors,这里主要是执行了ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 。

//org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(
    Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
	//ConfigrationClassPostProsessor
    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}
private final Set<Integer> registriesPostProcessed = new HashSet<>();
//org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);
    // 这里做了一个防重
    if (this.registriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
            "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    }
    if (this.factoriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + registry);
    }
    // 加入缓存
    this.registriesPostProcessed.add(registryId);

    processConfigBeanDefinitions(registry);
}

处理配置类

private ConfigurationClassBeanDefinitionReader reader;
//org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    //候选的配置类 BeanDefinitionHolder 集合
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    //获取候选BeanDefinitionName	这里包含引导类 其他类BeanN都是全名,是Spring内置配置类
    //candidateNames = {String[7]@4153} 
	// 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 = "Application"
	// 6 = "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"
    String[] candidateNames = registry.getBeanDefinitionNames();
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        //检查是不是候选类,就是被一些注解标注的类
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    // Return immediately if no @Configuration classes were found
    // 候选类是否为空,这里含有引导类,所以不为空
    if (configCandidates.isEmpty()) {
        return;
    }

    // Sort by previously determined @Order value, if applicable
    // 按 order 排序
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    // Detect any custom bean name generation strategy supplied through the enclosing application context
    SingletonBeanRegistry sbr = null;
    //registry = DefaultListableBeanFactory
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            //CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator"
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }
	//environment 已经初始化过了
    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }

    // Parse each @Configuration class
    // 创建Configuration 类的解析器 @Configuration 标注类
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);
	//候选类 配置类 包括引导类
    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    // 已经解析,注册的类
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        //解析 @Configuration 标注类,这里会解析引导类
        parser.parse(candidates);
        //处理 error 等 problemReporter
        parser.validate();
		//已经解析的类
        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());
        }
        //加载 并 注册
        this.reader.loadBeanDefinitions(configClasses);
        //将注册的类加入已经注册类集合
        alreadyParsed.addAll(configClasses);

        candidates.clear();
        //继续获取要加载注册的类,然后下一轮加载注册
        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());

    // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
        sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }

    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
        // Clear cache in externally provided MetadataReaderFactory; this is a no-op
        // for a shared cache since it'll be cleared by the ApplicationContext.
        ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
}

这里会先检查候选类,如果候选类为空,则结束。

解析候选类,包括Spring内建Bean和SpringBoot的引导类。

加载并注册。

2.1.1、判断是否候选类

//org.springframework.context.annotation.ConfigurationClassUtils#checkConfigurationClassCandidate
public static boolean checkConfigurationClassCandidate(
			BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
	//获取Class名称,这里还是处理的引导类
    String className = beanDef.getBeanClassName();
    if (className == null || beanDef.getFactoryMethodName() != null) {
        return false;
    }

    AnnotationMetadata metadata;
    //是否是被注解标注类
    if (beanDef instanceof AnnotatedBeanDefinition &&
        className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
        // Can reuse the pre-parsed metadata from the given BeanDefinition...
        // 获取注解元信息
        metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
    }
    else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
        // Check already loaded Class if present...
        // since we possibly can't even load the class file for this Class.
        Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
        if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
            BeanPostProcessor.class.isAssignableFrom(beanClass) ||
            AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
            EventListenerFactory.class.isAssignableFrom(beanClass)) {
            return false;
        }
        metadata = AnnotationMetadata.introspect(beanClass);
    }
    else {
        try {
            MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
            metadata = metadataReader.getAnnotationMetadata();
        }
        catch (IOException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Could not find class file for introspecting configuration annotations: " +
                             className, ex);
            }
            return false;
        }
    }
	//获取 @Configuration 标注元信息
    Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    //proxyBeanMethods 属性不为空
    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
        //org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass
        //full
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    // 被其他注解标注
    else if (config != null || isConfigurationCandidate(metadata)) {
        //lite
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {
        return false;
    }

    // It's a full or lite configuration candidate... Let's determine the order value, if any.
    //获取 order
    Integer order = getOrder(metadata);
    if (order != null) {
        beanDef.setAttribute(ORDER_ATTRIBUTE, order);
    }

    return true;
}

这个方法判断如果类没有被注解标注,就返回false。

引导类是被 @SpringBootApplication标注的,@SpringBootApplication 被@SpringBootConfiguration 标注,@SpringBootConfiguration 被 @Configuration 标注,所以引导类是候选类。

@Configuration注解中proxyBeanMethods 默认是true,所以引导类BeanDefinition属性中org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass 是 full。

如果@Configuration 注解 proxyBeanMethods 设置成false,则不是候选类,否则会判断是否被下面的五个注解(@Component, @ComponentScan, @Import, @ImportResource, @Bean)标注,如果被下面的五个注解标注了,也是候选类,BeanDefinition属性中org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass 是 lite。

2.1.1.1、判断是否被其他注解标注

private static final Set<String> candidateIndicators = new HashSet<>(8);
static {
    candidateIndicators.add(Component.class.getName());
    candidateIndicators.add(ComponentScan.class.getName());
    candidateIndicators.add(Import.class.getName());
    candidateIndicators.add(ImportResource.class.getName());
}
//org.springframework.context.annotation.ConfigurationClassUtils#isConfigurationCandidate
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
    // Do not consider an interface or an annotation...
    if (metadata.isInterface()) {
        return false;
    }

    // Any of the typical annotations found?
    for (String indicator : candidateIndicators) {
        if (metadata.isAnnotated(indicator)) {
            return true;
        }
    }

    // Finally, let's look for @Bean methods...
    try {
        return metadata.hasAnnotatedMethods(Bean.class.getName());
    }
    catch (Throwable ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
        }
        return false;
    }
}

2.1.1.2、获取order

//org.springframework.context.annotation.ConfigurationClassUtils#getOrder(org.springframework.core.type.AnnotationMetadata)
public static Integer getOrder(AnnotationMetadata metadata) {
    Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
    return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null);
}

2.1.2、创建配置类解析器

//元数据读取器工厂
private final MetadataReaderFactory metadataReaderFactory;
//spi 处理error 和 warn
private final ProblemReporter problemReporter;
private final Environment environment;
private final ResourceLoader resourceLoader;
private final BeanDefinitionRegistry registry;
//扫描注解解析器
private final ComponentScanAnnotationParser componentScanParser;
//condition 解析器
private final ConditionEvaluator conditionEvaluator;
public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory, ProblemReporter problemReporter, Environment environment, ResourceLoader resourceLoader, BeanNameGenerator componentScanBeanNameGenerator, BeanDefinitionRegistry registry) {

    this.metadataReaderFactory = metadataReaderFactory;
    this.problemReporter = problemReporter;
    this.environment = environment;
    this.resourceLoader = resourceLoader;
    this.registry = registry;
    this.componentScanParser = new ComponentScanAnnotationParser(
        environment, resourceLoader, componentScanBeanNameGenerator, registry);
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader);
}

版权声明:本文为xuwenjingrenca原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。