• SpringBoot 刷新上下文5--处理其他注解


    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.1.2、处理其他注解
    2.1.3.1.2.1、处理配置类内部的类
    //org.springframework.context.annotation.ConfigurationClassParser#processMemberClasses
    private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
    	//获取引导类的内部类,这里会递归处理
        Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
        if (!memberClasses.isEmpty()) {
            List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
            //获取内部类是配置类的类
            for (SourceClass memberClass : memberClasses) {
                if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
                    !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
                    candidates.add(memberClass);
                }
            }
            //排序
            OrderComparator.sort(candidates);
            //遍历
            for (SourceClass candidate : candidates) {
                // 处理 error warn的类
                if (this.importStack.contains(configClass)) {
                    this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
                }
                else {
                    this.importStack.push(configClass);
                    try {
                        //处理内部类是配置类的类	递归了
                        processConfigurationClass(candidate.asConfigClass(configClass), filter);
                    }
                    finally {
                        this.importStack.pop();
                    }
                }
            }
        }
    }
    
    • 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
    2.1.3.1.2.2、处理@PropertySource
    //org.springframework.context.annotation.ConfigurationClassParser#processPropertySource
    private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
        // 获取资源name
        String name = propertySource.getString("name");
        if (!StringUtils.hasLength(name)) {
            name = null;
        }
        // 获取 encoding
        String encoding = propertySource.getString("encoding");
        if (!StringUtils.hasLength(encoding)) {
            encoding = null;
        }
        // 获取 配置的值,资源的位置
        String[] locations = propertySource.getStringArray("value");
        Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
        boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
    
        Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
        PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
                                         DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
    	//遍历所有 配置的资源路径
        for (String location : locations) {
            try {
                //解析占位符,获取真实路径
                String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
                //读取资源
                Resource resource = this.resourceLoader.getResource(resolvedLocation);
                //创建PropertySource并添加到Environment的propertiSources
                addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
            }
            catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
                ...
            }
        }
    }
    
    • 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
    2.1.3.1.2.3、处理@Import

    这里默认会得到引导类 @SpringBootApplication 注解中 @EnableAutoConfigration 注解中配置的类,这个注解前面讲过,不再陈述解析过程。

    //org.springframework.context.annotation.ConfigurationClassParserprocessImports
    private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
    
        if (importCandidates.isEmpty()) {
            return;
        }
    
        if (checkForCircularImports && isChainedImportOnStack(configClass)) {
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
        }
        else {
            this.importStack.push(configClass);
            try {
                //遍历扫描到的 @Import 导入的类
                for (SourceClass candidate : importCandidates) {
                    //导入类是否派生自 ImportSelector
                    if (candidate.isAssignable(ImportSelector.class)) {
                        // Candidate class is an ImportSelector -> delegate to it to determine imports
                        //获取候选类的 class
                        Class<?> candidateClass = candidate.loadClass();
                        //加载候选类
                        ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                                                                                       this.environment, this.resourceLoader, this.registry);
                        Predicate<String> selectorFilter = selector.getExclusionFilter();
                        if (selectorFilter != null) {
                            exclusionFilter = exclusionFilter.or(selectorFilter);
                        }
                        //@EnableAutoConfigration 注解上配置类在这里处理,导入自动装配
                        // AutoConfigurationImportSelector
                        if (selector instanceof DeferredImportSelector) {
                            //将实现DeferredImportSelector的类加入
                            this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
                        }
                        else {
                            //执行候选类的 selectImports 方法获取要导入的类
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                            //递归处理
                            processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                        }
                    }
                    //是否派生自 ImportBeanDefinitionRegistrar
                    //class org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar
                    //@EnableAutoConfiguration 注解上标的类,获取扫描包
                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        // Candidate class is an ImportBeanDefinitionRegistrar ->
                        // delegate to it to register additional bean definitions
                        Class<?> candidateClass = candidate.loadClass();
                        ImportBeanDefinitionRegistrar registrar =
                            ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                                                                 this.environment, this.resourceLoader, this.registry);
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    }
                    else {
                        // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                        // process it as an @Configuration class
                        // 导入类不是ImportSelector 或 ImportBeanDefinitionRegistrar,
                        // 按配置类处理
                        this.importStack.registerImport(
                            currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                        //导入的其他类,递归处理
                        processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
                    }
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                    configClass.getMetadata().getClassName() + "]", ex);
            }
            finally {
                this.importStack.pop();
            }
        }
    }
    
    • 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

    将实现DeferredImportSelector的类加入集合

    private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
    //org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#handle
    public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
        DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
        if (this.deferredImportSelectors == null) {
            DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
            handler.register(holder);
            handler.processGroupImports();
        }
        else {
            //加入
            this.deferredImportSelectors.add(holder);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    2.1.3.1.2.4、处理@Bean
    private final MetadataReaderFactory metadataReaderFactory;
    //org.springframework.context.annotation.ConfigurationClassParser#retrieveBeanMethodMetadata
    private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
        //获取类注解
        AnnotationMetadata original = sourceClass.getMetadata();
        //获取@Bean 标注的所有方法
        Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
        if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
            // Try reading the class file via ASM for deterministic declaration order...
            // Unfortunately, the JVM's standard reflection returns methods in arbitrary
            // order, even between different runs of the same application on the same JVM.
            try {
                AnnotationMetadata asm =
                    this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
                Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
                if (asmMethods.size() >= beanMethods.size()) {
                    Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
                    for (MethodMetadata asmMethod : asmMethods) {
                        for (MethodMetadata beanMethod : beanMethods) {
                            if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
                                selectedMethods.add(beanMethod);
                                break;
                            }
                        }
                    }
                    if (selectedMethods.size() == beanMethods.size()) {
                        // All reflection-detected methods found in ASM method set -> proceed
                        beanMethods = selectedMethods;
                    }
                }
            }
            catch (IOException ex) {
                logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
                // No worries, let's continue with the reflection metadata we started with...
            }
        }
        return beanMethods;
    }
    
    • 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
    2.1.3.1.2.5、处理接口的默认方法
    //org.springframework.context.annotation.ConfigurationClassParser#processInterfaces
    private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
        for (SourceClass ifc : sourceClass.getInterfaces()) {
            //调用上面的方法,获取接口默认方法作为@Bean标注方法的方法
            Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
            for (MethodMetadata methodMetadata : beanMethods) {
                if (!methodMetadata.isAbstract()) {
                    // A default method or other concrete method on a Java 8+ interface...
                    configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
                }
            }
            //递归
            processInterfaces(configClass, ifc);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    istio学习(3)请求路由
    python 基础知识点(蓝桥杯python科目个人复习计划64)
    11.21~11.28日学习总结
    后端开发人员的Docker入门与实践指南
    我国平台经济领域“二选一”现象的成因、影响及对策
    基础算法---前缀和
    前端刷新token,判断token是否过期(jwt鉴权)
    4.物联网射频识别,RFID开发【智能门禁项目】
    spring 集成redisearch
    vue和react的相同点和不同点
  • 原文地址:https://blog.csdn.net/xuwenjingrenca/article/details/126574388