• SpringBoot 刷新上下文3--解析引导类


    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.3、解析引导类

    //org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set)
    public void parse(Set<BeanDefinitionHolder> configCandidates) {
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                //注解标记的
                if (bd instanceof AnnotatedBeanDefinition) {
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                }
                else {
                    parse(bd.getBeanClassName(), holder.getBeanName());
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                    "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
            }
        }
    	//这里处理 autoconfigration
        this.deferredImportSelectorHandler.process();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    2.1.3.1、注解标记类解析
    private static final Predicate<String> DEFAULT_EXCLUSION_FILTER = className ->
    			(className.startsWith("java.lang.annotation.") || className.startsWith("org.springframework.stereotype."));
    //org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)
    protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        //注解是 @org.springframework.boot.autoconfigure.SpringBootApplication(scanBasePackageClasses=[], excludeName=[], proxyBeanMethods=true, exclude=[], scanBasePackages=[])
        //beanName 是引导类的BeanName
        //这里会过滤掉其他的注解
        processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    处理配置类

    //org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
    protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
        // 判断Condition 系列注解,是否不解析该类
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }
    	//获取缓存
        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        //class已经存在 做防重
        if (existingClass != null) {
            //当前类是被导入的类,不再解析
            if (configClass.isImported()) {
                //合并
                if (existingClass.isImported()) {
                    existingClass.mergeImportedBy(configClass);
                }
                // Otherwise ignore new imported config class; existing non-imported class overrides it.
                return;
            }
            else {
                // Explicit bean definition found, probably replacing an import.
                // Let's remove the old one and go with the new one.
                // 不是被导入的类,从缓存中移除,继续解析
                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }
        }
    
        // Recursively process the configuration class and its superclass hierarchy.
        SourceClass sourceClass = asSourceClass(configClass, filter);
        do {
            sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
        }
        while (sourceClass != null);
    	//将class放入缓存
        this.configurationClasses.put(configClass, configClass);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    处理配置类

    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
        //是否被 @Component 标注
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // Recursively process any member (nested) classes first
            //处理引导类内部的类
            processMemberClasses(configClass, sourceClass, filter);
        }
    
        // 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) {
                //助理 @PropertySource
                processPropertySource(propertySource);
            }
            else {
                logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                            "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }
    
        // Process any @ComponentScan annotations
        // 处理 @ComponentScan 自己标注的,默认用@SpringBootApplication @ComponentScan是空的
        // 因为@SpringBootApplication 中包含了@ComponentScan
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        // @ComponentScan 注解非空 且 Condition 系列注解 不跳过
        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)) {
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }
    
        // Process any @Import annotations
        // 处理 @Import
        processImports(configClass, sourceClass, getImports(sourceClass), filter, 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);
        for (MethodMetadata methodMetadata : beanMethods) {
            // 添加 BeanMethod
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }
    
        // 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();
            }
        }
    
        // No superclass -> processing is complete
        return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    2.1.3.2、处理实现了DeferredImportSelector的类
    //org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#process
    public void process() {
        List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
        this.deferredImportSelectors = null;
        try {
            if (deferredImports != null) {
                DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
                deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
                deferredImports.forEach(handler::register);
                handler.processGroupImports();
            }
        }
        finally {
            this.deferredImportSelectors = new ArrayList<>();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    //org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports
    public void processGroupImports() {
        for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
            Predicate<String> exclusionFilter = grouping.getCandidateFilter();
            //获取所有import然后循环
            grouping.getImports().forEach(entry -> {
                ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
                try {
                    //递归处理import 同 2.1.3.1.5
                    processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter), 
    Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)), exclusionFilter, false);
                }
                catch (BeanDefinitionStoreException ex) {
                    throw ex;
                }
                catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                        "Failed to process import candidates for configuration class [" +
                        configurationClass.getMetadata().getClassName() + "]", ex);
                }
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    获取该group的所有导入类

    //org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGrouping#getImports
    public Iterable<Group.Entry> getImports() {
        //这里会导入 autoconfigration 的类
        for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
            //这里会调到 AutoConfigurationImportSelector.AutoConfigurationGroup#process
            //扫描所有 autoconfigration
            this.group.process(deferredImport.getConfigurationClass().getMetadata(),
                               deferredImport.getImportSelector());
        }
        return this.group.selectImports();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    上面两个 group的方法,添加到自动装配那一篇。

  • 相关阅读:
    模拟实现Hash-Table(线性探测)
    2024年阿里云服务器新用户购买一个月多少钱?
    PyQt5快速开发与实战 8.6 设置样式
    【Java集合类面试十八】、ConcurrentHashMap是怎么分段分组的?
    谷粒商城-商品服务(平台属性)
    Centos8怎么进行复位清屏? Centos8终端复位清屏的技巧
    Zorin OS 16.3 发布:无缝升级和卓越改进
    数据结构学习笔记—— 排序算法总结【ヾ(≧▽≦*)o所有的排序算法考点看这一篇你就懂啦!!!】
    C++面向对象Day02:C++ 类 & 对象
    计算机网络(三):数据链路层
  • 原文地址:https://blog.csdn.net/xuwenjingrenca/article/details/126574348