Spring ConfigurationClassParser

Spring ConfigurationClassParser

- ConfigurationClassPostProcessor.processConfigBeanDefinitions()
- 1.获取 registry 中的 beanDefinitionNames
- 2.遍历beanDefinitionNames判断beanDefinition 是否是 @Configuration 配置类,若是则添加到 configCandidates 集合中
- 3.configCandidates根据Order排序
- 4.创建ConfigurationClassParser,配置类解析器
- 5.遍历configCandidates,调用parser.parse()进行配置类解析
    - ConfigurationClassParser.parse()
    - 1.遍历configCandidates,获取当前的beanDefinition
    - 2.根据不同类型的beanDefinition,调用不同入参的parse()方法
        - ConfigurationClassParser.processConfigurationClass()
        - 1.是否需要跳过 @Conditional
        - 2.循环递归调用doProcessConfigurationClass()方法,处理配置类和父类,直到没有父类时,方法返回null,结束循环
            - ConfigurationClassParser.doProcessConfigurationClass()
            - 1.判断是否含有 @Component 注解,首先递归处理任何成员(嵌套)类
            - 2.若有PropertySources注解,循环处理 @PropertySource 注解
            - 3.若有@ComponentScan注解,处理 @ComponentScan 注解
            - 4.处理 @Import 注解
            - 5.若有 @ImportResource 注解,处理 @ImportResource 注解
            - 6.处理 @Bean 注解的方法
            - 7.如果有父类,获取父类名,外层循环会继续调用该方法解析父类.没有父类返回null,结束循环
- 6.loadBeanDefinitions() 把前面解析出来的对象注册到容器中

ConfigurationClassParser.doProcessConfigurationClass()

/** 通过解析源类中的 注解、成员 和 方法,创建 ConfigurationClass
    * Apply processing and build a complete {@link ConfigurationClass} by reading the
    * annotations, members and methods from the source class. This method can be called
    * multiple times as relevant sources are discovered.
    * @param configClass the configuration class being build
    * @param sourceClass a source class
    * @return the superclass, or {@code null} if none found or previously processed
    */
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
        throws IOException {

    if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // 含有 @Component 注解
        // Recursively process any member (nested) classes first.首先递归处理任何成员(嵌套)类
        processMemberClasses(configClass, sourceClass);
    }

    // Process any @PropertySource annotations. 处理 @PropertySource
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), PropertySources.class,
            org.springframework.context.annotation.PropertySource.class)) {
        if (this.environment instanceof ConfigurableEnvironment) {
            processPropertySource(propertySource);
        }
        else {
            logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                    "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    // Process any @ComponentScan annotations. 处理 @ComponentScan 注解
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
            !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            // The config class is annotated with @ComponentScan -> perform the scan immediately
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
            // Check the set of scanned definitions for any further config classes and parse recursively if needed
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                    bdCand = holder.getBeanDefinition();
                }
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { // 判断解析获取的 BeanDefinition 中 是否有配置类.也就是说只要有 @Configuration、@Component、@ComponentScan、@Import、@ImportResource 和 @Bean 中的其中一个注解
                    parse(bdCand.getBeanClassName(), holder.getBeanName()); // 如果有配置类,递归调用,解析该配置类
                }
            }
        }
    }

    // Process any @Import annotations. 处理 @Import 注解
    processImports(configClass, sourceClass, getImports(sourceClass), true);

    // Process any @ImportResource annotations. 处理 @ImportResource 注解
    AnnotationAttributes importResource =
            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {
        String[] resources = importResource.getStringArray("locations");
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
        for (String resource : resources) {
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    // Process individual @Bean methods. 处理 @Bean 方法
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); // 检索 @Bean 方法
    for (MethodMetadata methodMetadata : beanMethods) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); // 创建 BeanMethod,添加到 beanMethods
    }

    // Process default methods on interfaces
    processInterfaces(configClass, sourceClass);

    // Process superclass, if any. 如果有父类,则解析父类
    if (sourceClass.getMetadata().hasSuperClass()) {
        String superclass = sourceClass.getMetadata().getSuperClassName();
        if (superclass != null && !superclass.startsWith("java") &&
                !this.knownSuperclasses.containsKey(superclass)) {
            this.knownSuperclasses.put(superclass, configClass);
            // Superclass found, return its annotation metadata and recurse
            return sourceClass.getSuperClass(); // 不返回null,外层循环调用
        }
    }

    // No superclass -> processing is complete
    return null; // 循环出口.没有父类,处理完成,返回null,外层结束循环
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlyingZCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值