zoukankan      html  css  js  c++  java
  • ConfigurationClassParser类的parse方法源码解析

    spring版本为5.0.11

    ConfigurationClassPostProcessor对配置类的解析
    public void parse(Set<BeanDefinitionHolder> configCandidates) {
            //List<ConfigurationClassParser.DeferredImportSelectorHolder> deferredImportSelectors 进行初始化 
            this.deferredImportSelectors = new LinkedList();
            Iterator var2 = configCandidates.iterator();
            //循环遍历需要处理的配置类
            while(var2.hasNext()) {
                BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
                BeanDefinition bd = holder.getBeanDefinition();
                //根据BeanDefinition实例判断调用哪个,其实最后还是调用
                //核心方法:processConfigurationClass(ConfigurationClass configClass)
                try {
                    if (bd instanceof AnnotatedBeanDefinition) {
                        this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
                    } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
                        this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
                    } else {
                        this.parse(bd.getBeanClassName(), holder.getBeanName());
                    }
                } catch (BeanDefinitionStoreException var6) {
                    throw var6;
                } catch (Throwable var7) {
                    throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
                }
            }
            //字面理解:处理延迟导入的javabean
            //parse方法,把被处理的类实现DeferredImportSelector接口,加入deferredImportSelectors集合中,
            //处理deferredImportSelectors集合种类
            this.processDeferredImportSelectors();
        }

    parse调用核心方法processConfigurationClass(ConfigurationClass configClass)解析

    protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
            //检查当前解析的配置bean是否包含Conditional注解,如果不包含则不需要跳过
            // 如果包含了则进行match方法得到匹配结果,如果是符合的并且设置的配置解析策略是解析阶段不需要调过
            if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
                //在这里处理Configuration重复import
                //如果同一个配置类被处理两次,两次都属于被import的则合并导入类,返回。如果配置类不是被导入的,则移除旧使用新的配置类
                ConfigurationClass existingClass = (ConfigurationClass)this.configurationClasses.get(configClass);
                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;
                    }
                    // 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.
                ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass);
                //递归解析
                do {
                    sourceClass = this.doProcessConfigurationClass(configClass, sourceClass);
                } while(sourceClass != null);
                // 添加到ConfigurationClassParser的configurationClasses中
                this.configurationClasses.put(configClass, configClass);
            }
        }

    递归解析,调用doProcessConfigurationClass方法,终于到了解析的地方!!

    总结一下:

    1.处理内部类

    2.处理@PropertySource注解

    3.处理@ComponentScan注解

    4.处理@Import注解

    5.处理@ImportResource注解

    6.处理@Bean修饰的方法

    7.处理接口定义的方法

    8.处理父类

    protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass) throws IOException {
            // Recursively process any member (nested) classes first 处理内部类
            this.processMemberClasses(configClass, sourceClass);
            // Process any @PropertySource annotations
            // 处理@PropertySource注解
            Iterator var3 = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, PropertySource.class).iterator();
    
            AnnotationAttributes importResource;
            while(var3.hasNext()) {
                importResource = (AnnotationAttributes)var3.next();
                if (this.environment instanceof ConfigurableEnvironment) {
                    this.processPropertySource(importResource);
                } else {
                    this.logger.warn("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)) {
                Iterator var13 = componentScans.iterator();
                // The config class is annotated with @ComponentScan -> perform the scan immediately
                //扫描
                while(var13.hasNext()) {
                    AnnotationAttributes componentScan = (AnnotationAttributes)var13.next();
                    Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                    Iterator var7 = scannedBeanDefinitions.iterator();
                    // Check the set of scanned definitions for any further config classes and parse recursively if necessary
                    //遍历扫描到的配置类进行递归解析
                    while(var7.hasNext()) {
                        BeanDefinitionHolder holder = (BeanDefinitionHolder)var7.next();
                        BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                        if (bdCand == null) {
                            bdCand = holder.getBeanDefinition();
                        }
    
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                            this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                        }
                    }
                }
            }
            // Process any @Import annotations
            // 处理@Import注解
            this.processImports(configClass, sourceClass, this.getImports(sourceClass), true);
            // Process any @ImportResource annotations.
            // 处理@ImportResource 注解
            importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
            if (importResource != null) {
                String[] resources = importResource.getStringArray("locations");
                Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
                String[] var19 = resources;
                int var21 = resources.length;
                // 遍历配置的locations,加入到configClass 中的ImportedResource
                for(int var22 = 0; var22 < var21; ++var22) {
                    String resource = var19[var22];
                    String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                    configClass.addImportedResource(resolvedResource, readerClass);
                }
            }
            // Process individual @Bean methods
            // 处理@Bean修饰的方法
            Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
            Iterator var17 = beanMethods.iterator();
    
            while(var17.hasNext()) {
                MethodMetadata methodMetadata = (MethodMetadata)var17.next();
                configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
            }
            // Process default methods on interfaces
            // 处理接口定义的方法
            this.processInterfaces(configClass, sourceClass);
            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.处理内部类(递归解析)

    private void processMemberClasses(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass) throws IOException {
            //读取配置类中所有成员类
            Collection<ConfigurationClassParser.SourceClass> memberClasses = sourceClass.getMemberClasses();
            if (!memberClasses.isEmpty()) {
                List<ConfigurationClassParser.SourceClass> candidates = new ArrayList(memberClasses.size());
                Iterator var5 = memberClasses.iterator();
                //过滤出配置类
                ConfigurationClassParser.SourceClass candidate;
                while(var5.hasNext()) {
                    candidate = (ConfigurationClassParser.SourceClass)var5.next();
                    if (ConfigurationClassUtils.isConfigurationCandidate(candidate.getMetadata()) && !candidate.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
                        candidates.add(candidate);
                    }
                }
                //根据Order进行排序
                OrderComparator.sort(candidates);
                var5 = candidates.iterator();
                //遍历
                while(var5.hasNext()) {
                    candidate = (ConfigurationClassParser.SourceClass)var5.next();
                    //1)出现配置类循环导入,直接报错
                    if (this.importStack.contains(configClass)) {
                        this.problemReporter.error(new ConfigurationClassParser.CircularImportProblem(configClass, this.importStack));
                    } else {
                        //将配置类入栈
                        this.importStack.push(configClass);
    
                        try {
                            //处理配置类
                            this.processConfigurationClass(candidate.asConfigClass(configClass));
                        } finally {
                            //解析完出栈
                            this.importStack.pop();
                        }
                    }
                }
            }
    
        }

    2.处理@PropertySource注解

     如果配置类上有@PropertySource注解,则解析加载properties文件,并将属性添加到Spring上下文中。

    this.addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));

    3.处理@ComponentScan注解

    获取配置类上的@ComponentScan注解,判断是否需要跳过。循环所有的ComponentScan,立即执行扫描。

    // Process any @ComponentScan annotations
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
            if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
                Iterator var13 = componentScans.iterator();
    
                while(var13.hasNext()) {
                    AnnotationAttributes componentScan = (AnnotationAttributes)var13.next();
                    // The config class is annotated with @ComponentScan -> perform the scan immediately
                    Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                    Iterator var7 = scannedBeanDefinitions.iterator();
                    // Check the set of scanned definitions for any further config classes and parse recursively if needed
                    while(var7.hasNext()) {
                        BeanDefinitionHolder holder = (BeanDefinitionHolder)var7.next();
                        BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                        if (bdCand == null) {
                            bdCand = holder.getBeanDefinition();
                        }
                        //检验扫描获得的BeanDefinition中是否有配置类,如果有配置类,这里的配置类包括FullConfigurationClass和LiteConfigurationClass。
                        //(也就是说只要有@Configuration、@Component、@ComponentScan、@Import、@ImportResource和@Bean中的其中一个注解),则递归调用parse方法,进行解析。
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                            this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                        }
                    }
                }
            }

    4.处理@Import注解

    this.processImports(configClass, sourceClass, this.getImports(sourceClass), true);
    processImports方法负责对@Import注解进行解析。configClass是配置类,sourceClass又是通过configClass创建的,getImports(sourceClass)sourceClass获取所有的@Import注解信息
    private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection<ConfigurationClassParser.SourceClass> importCandidates, boolean checkForCircularImports) {
            if (!importCandidates.isEmpty()) {
                //循环导入直接报错
                if (checkForCircularImports && this.isChainedImportOnStack(configClass)) {
                    this.problemReporter.error(new ConfigurationClassParser.CircularImportProblem(configClass, this.importStack));
                } else {
                    //推入栈
                    this.importStack.push(configClass);
    
                    try {
                        Iterator var5 = importCandidates.iterator();
                        //循环遍历
                        while(true) {
                            while(true) {
                                while(var5.hasNext()) {
                                    ConfigurationClassParser.SourceClass candidate = (ConfigurationClassParser.SourceClass)var5.next();
                                    Class candidateClass;
                                    //对import的内容进行分类
                                    // import导入实现ImportSelector接口的类
                                    if (candidate.isAssignable(ImportSelector.class)) {
                                        // Candidate class is an ImportSelector -> delegate to it to determine imports
                                        candidateClass = candidate.loadClass();
                                        // 反射创建这个类的实例对象
                                        ImportSelector selector = (ImportSelector)BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                                        //是否有实现相关Aware接口,如果有,这调用相关方法
                                        ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);
                                        // 延迟加载的ImportSelector
                                        if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                                            //  延迟加载的ImportSelector先放到List中,延迟加载
                                            this.deferredImportSelectors.add(new ConfigurationClassParser.DeferredImportSelectorHolder(configClass, (DeferredImportSelector)selector));
                                        } else {
                                            // 普通的ImportSelector ,执行其selectImports方法,获取需要导入的类的全限定类名数组
                                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                                            Collection<ConfigurationClassParser.SourceClass> importSourceClasses = this.asSourceClasses(importClassNames);
                                            // 递归调用
                                            this.processImports(configClass, currentSourceClass, importSourceClasses, false);
                                        }
                                        // 是否为ImportBeanDefinitionRegistrar
                                    } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                                        // Candidate class is an ImportBeanDefinitionRegistrar ->
                                        // delegate to it to register additional bean definitions
                                        candidateClass = candidate.loadClass();
                                        ImportBeanDefinitionRegistrar registrar = (ImportBeanDefinitionRegistrar)BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                                        ParserStrategyUtils.invokeAwareMethods(registrar, 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
                                        // 普通 @Configuration class
                                        this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                                        // 解析导入的@Configuration class
                                        this.processConfigurationClass(candidate.asConfigClass(configClass));
                                    }
                                }
    
                                return;
                            }
                        }
                    } catch (BeanDefinitionStoreException var15) {
                        throw var15;
                    } catch (Throwable var16) {
                        throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", var16);
                    } finally {
                        this.importStack.pop();
                    }
                }
            }
        }

    5.处理@ImportResource注解

    @ImportResource注解可以导入xml配置文件。

    // Process any @ImportResource annotations
    importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
            if (importResource != null) {
                String[] resources = importResource.getStringArray("locations");
                Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
                String[] var19 = resources;
                int var21 = resources.length;
    
                for(int var22 = 0; var22 < var21; ++var22) {
                    String resource = var19[var22];
                    String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                    //把配置项提取出来,跟reader一起放入configClass的map中,
                    //接下来会在ConfigurationClassPostProcessor类中processConfigBeanDefinitions方法中,解析完,
                    //this.reader.loadBeanDefinitions(configClasses)这方法会对@import处理(对ImportBeanDefinitionRegistrars的处理)
                    configClass.addImportedResource(resolvedResource, readerClass);
                }
            }

    6.处理@Bean修饰的方法

    @Bean方法转化为BeanMethod对象

    Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
            Iterator var17 = beanMethods.iterator();
    
            while(var17.hasNext()) {
                MethodMetadata methodMetadata = (MethodMetadata)var17.next();
                //添加到configClass的beanMethods集合中,接下来,会在this.reader.loadBeanDefinitions(configClasses)这方法
                //得到处理
                configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
            }

    7.处理接口定义的方法

    this.processInterfaces(configClass, sourceClass);

    8.处理父类

    if (sourceClass.getMetadata().hasSuperClass()) {
                String superclass = sourceClass.getMetadata().getSuperClassName();
                if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
                    this.knownSuperclasses.put(superclass, configClass);
                    return sourceClass.getSuperClass();
                }
            }

    如果有父类则返回父类Class对象,继续调用该方法。直到返回null,外层循环结束。

    do {
                sourceClass = doProcessConfigurationClass(configClass, sourceClass);
            }
            while (sourceClass != null);
  • 相关阅读:
    20191119PHP.class类练习
    20191115PHP cookie登入实例
    Jenkins详细教程
    Navicat 破解
    测试_离职_交接内容
    ETL方法与过程讲
    ETL测试或数据仓库测试入门
    大数据基础了解-(基础01)
    adb调试显示adb: usage: unknown command device
    hive 创建/删除/截断 表(翻译自Hive wiki)
  • 原文地址:https://www.cnblogs.com/mufeng07/p/12172549.html
Copyright © 2011-2022 走看看