专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

ConfigurationClassPostProcessor-2. parser-doProcessConfigurationClass

2、parse

public void parse(Set<BeanDefinitionHolder> configCandidates) {
        Iterator var2 = configCandidates.iterator();

        while(var2.hasNext()) {
            BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
            BeanDefinition bd = holder.getBeanDefinition();

            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);
            }
        }
        //这句话非常非常重要
        this.deferredImportSelectorHandler.process();
    }
      protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        this.processConfigurationClass(new ConfigurationClass(metadata, beanName));
    }

processConfigurationClass

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
        if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            ConfigurationClass existingClass = (ConfigurationClass)this.configurationClasses.get(configClass);
            if (existingClass != null) {
                if (configClass.isImported()) {
                    if (existingClass.isImported()) {
                        existingClass.mergeImportedBy(configClass);
                    }

                    return;
                }

                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }

            ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass);

            do {
               //一看这个就是主要逻辑地方所在
               //doProcessConfigurationClass中具体的加载逻辑会反反复复的调用processConfigurationClass这个方法
               //写的特别饶
                sourceClass = this.doProcessConfigurationClass(configClass, sourceClass);
            } while(sourceClass != null);

            this.configurationClasses.put(configClass, configClass);
        }
    }

doProcessConfigurationClass

这个方法也挺长

1.第一步 处理内部

加载compotent注解的类

 if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            this.processMemberClasses(configClass, sourceClass);
        }

1.1 processMemberClasses

private void processMemberClasses(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass) throws IOException {
        Collection<ConfigurationClassParser.SourceClass> memberClasses = sourceClass.getMemberClasses();
        //默认情况下memberClasses为空,咱不分析
        if (!memberClasses.isEmpty()) {
            .......
        }

    }

2. 第二步处理属性资源文件,加了@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.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

3. 第三步 处理扫描类

// 3.1 先找出类上的@ComponentScan和@ComponentScans注解的所有属性(例如basePackages等属性值)
  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();
                // 3.2 解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类
                 //如果没配的话会默认扫描包
                 /**
                  if (basePackages.isEmpty()) {
                     //这里就是启动类
                    basePackages.add(ClassUtils.getPackageName(declaringClass));
                   }
                 */
                 // (BeanDefinition可以理解为等价于BeanDefinitionHolder)
                Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                Iterator var7 = scannedBeanDefinitions.iterator();

                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)) {
                        //注意这里的parse最终会回到processConfigurationClass这个方法
                        this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

在这一步会把当前包所在的类和配置的ComponentScan所在报的类加载 因为我只写了一个helloController 在这里加载了 到目前为止的注册的类有这些

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"
7 = "helloController"

4. 第四步 处理import

// 4.处理Import注解注册的bean,这一步只会将import注册的bean变为ConfigurationClass,不会变成BeanDefinition
    // 而是在loadBeanDefinitions()方法中变成BeanDefinition,再放入到BeanDefinitionMap中
    // 关于Import注解,后面会单独写文章介绍
    processImports(configClass, sourceClass, getImports(sourceClass), true);

5.第五步 处理@ImportResource注解引入的配置文件

// 5.处理@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);
        }
    }

6. 第六步 处理加了@Bean注解的方法

// 处理加了@Bean注解的方法
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

7.第七步 processInterfaces

 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);
                return sourceClass.getSuperClass();
            }
        }

整个方法基本实现了各种类的加载,属于基础方法

文章永久链接:https://tech.souyunku.com/23625

未经允许不得转载:搜云库技术团队 » ConfigurationClassPostProcessor-2. parser-doProcessConfigurationClass

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们