SpringBoot启动过程(三)class 变成 beanDefinition

Spring Boot 启动过程:
1. 创建 SpringApplication 对象。
2. 执行对象的 run() 方法。
3. 将 class 变成 beanDefinition。
4. 将 beanDefinition 变成 bean
5. 图解 循环依赖
6. 图解 bean 的生命周期
7. 图解 aop 拦截器链调用

Spring Boot 在启动是执行了自动配置:class --> beanDefinition --> bean。这篇文章主要想梳理下:class 是怎么变成 beanDefinition 的。上一篇博客提到过,执行 run 方法中 invokeBeanFactoryPostProcessors(beanFactory) 方法执行了这一变换,看下这个方法了到了干了什么?

1. invokeBeanFactoryPostProcessors

/** AbstractApplicationContext.java
	Instantiate and invoke all registered BeanFactoryPostProcessor beans, respecting explicit order if given.
Must be called before singleton instantiation.
	必须在 class 变成 bean 之前,按照给定的顺序(如果有)实例化所有已注册的 beanFactoryPostProcessor。
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 执行每一个 beanFactoryPostProcessor。
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	
    if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        // 注册了一个beanPostProcessor。 
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // 设置类加载器。
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

//--------------------------------------
// 从 context 中获取已有的 beanFactoryPostProcessor。
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
    return this.beanFactoryPostProcessors;
}

很明显了,接下来要看下 beanFactoryPostProcessor 是怎么执行的。

2. invokeBeanFactoryPostProcessors

别看代码这么长,就解决了两个问题:

  1. 多个 beanFactoryPostProcessor,哪个先执行,哪个后执行?
  2. 每一个 beanFactoryPostProcessor 到底执行了什么?
  3. 这些 beanFactoryPostProcessor 是从哪里拿到的?(换句话说,它存放在哪里?)

执行顺序:

public interface BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
// -----------------
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

规则1:实现 BeanDefinitionRegistryPostProcessor 的类先执行,只实现 BeanFactoryPostProcessor 类的接口后执行。

规则2:在规则1 的基础上,实现 PriorityOrdered 的类先执行,实现 Ordered 的类后执行,最后执行既没实现 PriorityOrdered ,也没实现 Ordered 的类。

// 执行顺序
1. Class implements BeanDefinitionRegistryPostProcessor, PriorityOrdered;
2. Class implements BeanDefinitionRegistryPostProcessor, Ordered;
3. Class implements BeanDefinitionRegistryPostProcessor;
4. Class implements BeanFactoryPostProcessor, PriorityOrdered;
5. Class implements BeanFactoryPostProcessor, Ordered;
6. Class implements BeanFactoryPostProcessor;

执行了什么:

每一个 BeanFactoryPostProcessor 的实现类在这里只执行了接口方法。也就是说:

Class implements BeanDefinitionRegistryPostProcessor

先执行postProcessBeanDefinitionRegistry 方法,再执行postProcessBeanFactory 方法。

Class implements BeanFactoryPostProcessor 只执行 postProcessBeanFactory 方法。

从哪里拿的:

有两个地方:

第一种,可能 BeanFactoryPostProcessor 已经实例化成了 bean,那么它存放在 context 的 beanFactoryPostProcessors属性中;

第二种,BeanFactoryPostProcessor还没有实例化,目前仅仅之是个“蓝图”(beanDefinition),那么它存放在 context 的 beanFactory 属性的 beanDefinitionMap 属性中。

接下来看下源码:

public static void invokeBeanFactoryPostProcessors(
    // beanFactoryPostProcessors 是从 context 中直接拿的 bean。
    ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    // 保存已经处理过的 beanName。
    Set<String> processedBeans = new HashSet<>();
	// beanFactory 是实例是 DefaultListableBeanFactory,它实现了 BeanDefinitionRegistry 接口。
    if (beanFactory instanceof BeanDefinitionRegistry) {
        // 向上转型
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // 保存常规的 beanFactoryPostProcessor,没实现 BeanDefinitionRegistryPostProcessor 接口的都是常规的。
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        // 保存非常规的 beanFactoryPostProcessor。
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
		// 遍历已经注册的 beanFactoryPostProcessor。
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            // 判断是否是非常规的。如果是,那就具有优先执行权。
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                // 类型转换,不然拿不到方法。
                BeanDefinitionRegistryPostProcessor registryProcessor =
                    (BeanDefinitionRegistryPostProcessor) postProcessor;
                // 执行 postProcessBeanDefinitionRegistry
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                // 保存到 registryProcessors,为什么要保存?因为这货还有一个方法没执行呢。
                registryProcessors.add(registryProcessor);
            }
            else {
                // 如果 postProcessor 是常规的,那它优先级不够,先保存。
                regularPostProcessors.add(postProcessor);
            }
        }
        // 到这里,bean 形式的 beanFactoryPostProcessor 已经拿出来了,并且执行了最高优先级的方法。 
        // 接下来要拿 “蓝图” 形式的了。
        
        // 用来保存 beanDefinition 形式的 BeanDefinitionRegistryPostProcessor。 
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        // 从 beanDefinitionMap 中获取与 BeanDefinitionRegistryPostProcessor.class 类型匹配的 beanDefinition
        // 的 name。
        String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        // 遍历
        for (String ppName : postProcessorNames) {
            // 判断 ppName 对应的 beanDefinition 是不是最高优先级。
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 如果是最高优先级,用 beanDefinition 创建 bean,并经创建出来的 bean 保存到 currentRegistryProcessors。
                // beanFactory.getBean()先去 beanFactory 中找,有没有 ppName 对应的 bean,
                // 如果有,直接拿出来;如果没有,先创建bean,并保存到 beanFactory,最后再将 bean 返回。
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                // ppName 添加到 processedBeans。
                processedBeans.add(ppName);
            }
        }
        // 如果有多个同时具备最最高优先级,那他们之间也是需要在排序的。(这个不是重点)
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        // 保存到 registryProcessors。
        registryProcessors.addAll(currentRegistryProcessors);
        // 执行每一个 beanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法。
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        // Class implements BeanDefinitionRegistryPostProcessor, PriorityOrdered 就算是执行完了。
        // 清空 currentRegistryProcessors,因为后面还要用。
        currentRegistryProcessors.clear();

        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        // 接下来执行:Class implements BeanDefinitionRegistryPostProcessor, Ordered
        
        // 拿名字
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        // 遍历
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                // 拿出 beanDefinitionRegistryPostProcessor,并保存到 currentRegistryProcessors。
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // 排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        // 保存 
        registryProcessors.addAll(currentRegistryProcessors);
        // 执行每一个 beanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法。
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        // 清空
        currentRegistryProcessors.clear();

        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        // 最后执行 Class implements BeanDefinitionRegistryPostProcessor
        
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    // 如果能拿到,当然还要执行循环。
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();
        }

        // registryProcessors 保存的是非常规的 beanFactoryPostProcessor,
        // 它还有个 postProcessBeanFactory 没执行呢。  
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        // 常规的 beanFactoryPostProcessor 也在这里执行 postProcessBeanFactory 方法。
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
        // Invoke factory processors registered with the context instance.
        // 如果 beanFactory 没有实现 BeanDefinitionRegistry 接口,才会走到这里。
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    /**
    	4. Class implements BeanFactoryPostProcessor, PriorityOrdered;
		5. Class implements BeanFactoryPostProcessor, Ordered;
		6. Class implements BeanFactoryPostProcessor;
		
		流程跟 1、2、3 几乎是一样的,就不写了注释了。
    */
    
    String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    // 清缓存
    beanFactory.clearMetadataCache();
}

这一层的代码逻辑还是很简单的。不过接下来会出现一个货,很重要也和复杂。

3. ConfigurationClassPostProcessor 把 class 变成 bean

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware {
    // 属性和方法就省略了,看它实现的接口就明白了。
}

ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,PriorityOrdered 说明这个类在 上面的代码中肯定是先执行了 postProcessBeanDefinitionRegistry() 后执行了 postProcessBeanFactory() ,而且还是以最高优先级执行的。 postProcessBeanDefinitionRegistry() 方法执行的时候,它将需要自动配置的 class 变成了 bean

3.1 ConfigurationClassPostProcessor 是怎么来的?

在 run() 方法中实例化 context 时,框架就默认加载了 一些 beanDefinition 并保存在 context 的 beanFactory 属性的 definitionMap 属性中。

// 被加载部分的 beanDefinition
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor" \
= ConfigurationClassPostProcessor.class; //(看这里)
"org.springframework.context.event.internalEventListenerFactory" \
= DefaultEventListenerFactory.class;
"org.springframework.context.event.internalEventListenerProcessor" \
= EventListenerMethodProcessor.class;
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor" \
= AutowiredAnnotationBeanPostProcessor.class;
"org.springframework.context.annotation.internalCommonAnnotationProcessor" \
= CommonAnnotationBeanPostProcessor.class;

具体的加载流程如下:

// springApplition.java ------------------- 1
public ConfigurableApplicationContext run(String... args) {
	//......上面省略.......
    context = createApplicationContext();
    //......下面省略.......
}	
// springApplition.java ------------------- 2
protected ConfigurableApplicationContext createApplicationContext() {
    return this.applicationContextFactory.create(this.webApplicationType);
}
// ApplicationContextFactory.java --------- 3
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
    try {
        switch (webApplicationType) {
            case SERVLET:
                // 走这里,context的实际类型是 AnnotationConfigServletWebServerApplicationContext。
                return new AnnotationConfigServletWebServerApplicationContext();
            case REACTIVE:
                return new AnnotationConfigReactiveWebServerApplicationContext();
            default:
                return new AnnotationConfigApplicationContext();
        }
    }
    catch (Exception ex) {
        throw new IllegalStateException("Unable create a default ApplicationContext instance, "
                                        + "you may need a custom ApplicationContextFactory", ex);
    }
};
// AnnotationConfigServletWebServerApplicationContext.java ----- 4
// 这是构造器。
public AnnotationConfigServletWebServerApplicationContext() {
    // reader 读取了那四个 beanDefinition。
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}
// AnnotatedBeanDefinitionReader.java -------------------------- 5
// 这也是构造器。
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}
// AnnotatedBeanDefinitionReader.java -------------------------- 6
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
	//......上面省略.......
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
// AnnotationConfigUtils.java ---------------------------------- 7
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, null);
}
// AnnotationConfigUtils.java ---------------------------------- 8
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
	//......上面省略.......
    // registry 就是 beanFactory, 判断 beanFactory 有没有?
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // 如果没有,构造 ConfigurationClassPostProcessor 的 beanDefinition。
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        // registerPostProcessor()将键值对CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME:def 注册到 registory 中。
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // 其他三个也是这么注册进去的,这里就不贴代码了。
}

写到这里还是能说的通的,ConfigurationClassPostProcessor 在 context 实例化时就以 beanDefinition 的形式注册到了 beanFactory 中。在 invokeBeanFactoryPostProcessors() 方法中,根据 ConfigurationClassPostProcessor.class 去 beanFactory 中找匹配的 beanDefinition,再去 beanFactory 中拿对应的bean,没有拿到,所以就根据 beanDefinition 创建了 ConfigurationClassPostProcessor 对应的 bean,最后执行其 processConfigBeanDefinitions(BeanDefinitionRegistry registry) 方法,完成了需要自动配置的类的注册。

3.2 processConfigBeanDefinitions(BeanDefinitionRegistry registry)

class --> bean 阶段中最复杂的地方出现了,不过还是尽量将这块的内容写清楚。

/** ConfigurationClassPostProcessor.java
	从配置类中生成 beanDefinition 注册到 registory 中。
    入口参数的 registry 实际上是 DefaultListableBeanFactory。
*/
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);
    if (this.registriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
            "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    }
    if (this.factoriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + registry);
    }
    this.registriesPostProcessed.add(registryId);
	// 上面代码都不重要,从这里开始看,处理配置 beanDefinition。
    processConfigBeanDefinitions(registry);
}

看下面源码之前,先说一个小细节,不然会懵的。启动类(被@SpringBootApplication注解的类)的 beanDefinition 在执行 run() 方法中的 prepareContext() 方法中的 load(context, sources.toArray(new Object[0])) 方法时,被注册到了 beanFactory 中。

/** ConfigurationClassPostProcessor.java
	registry 实际上是 DefaultListableBeanFactory 类型的对象。
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    // BeanDefinitionHolder 是对 BeanDefinition 的包装。
    // configCandidates 用来保存所有的需要自动配置的类的 beanDefinitionHolder。
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    // 获取已经注册的所有 beanDefinition 的 name。
    String[] candidateNames = registry.getBeanDefinitionNames();
	// 遍历 candidateNames
    for (String beanName : candidateNames) {
        // 依据 beanName 从 beanFactory 中拿对应的 beanDefinition。
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        // 判断 beanDefinition 中有没有 “org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass” 属性?
        // (实际测试的结果是都没有这个属性)
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnabled()) {
                //(根据这里的日志推测,上面是在检查:beanDef是不是已经作为配置类处理过了?)
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        // 检查 beanDef 是否是个配置类的候选者,如果是做个标记。
        // beanDef 拥有 @Configuration 或 @Component 或 @ComponentScan 或 @Import 或 @ImportResource 其中的
        // 一个注解,那它就是配置类的后选择。
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            // 将配置类后选者 beanDef 添加到 configCandidates 中。
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }
    //(上面测试的结果是:只有主启动类对应的 beanDefinition 添加到了configCandidates 中。)

    // Return immediately if no @Configuration classes were found
    // 如果没有配置后选择,也就是说已注册的 beanDefinition 都不需要自动配置,那么直接返回吧。
    if (configCandidates.isEmpty()) {
        return;
    }

    // Sort by previously determined @Order value, if applicable
    // 对 configCandidates 中元素依据 @Order 注解进行排序。
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    // Detect any custom bean name generation strategy supplied through the enclosing application context
    /**
    	这里是创造一个 beanName 生成器。具体规则如下:
    	1. 先在 applicationContext 中找有没有自定义的 bean name 生成器。(默认没有自定义的)
    	2. 如果没有自定义的,那就使用默认的。
    	默认情况下:
    	- componentScanBeanNameGenerator 使用简短的类名作为 bean name。
    	- importBeanNameGenerator 使用全限定类名作为 bean name。
    */
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }
    
	// 设置环境属性。
    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }

    // Parse each @Configuration class
    // 创建配置类解析器 parser,后面就是使用它 寻找 并 解析 所有的配置类。
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);
	
    //  拷贝一份 configCandidates,后面要使用。里面只有一个主启动类的 beanDefinitionHolder。
    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    // alreadyParsed 保存已经解析到配置类。 
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        // 记录阶段信息,
        StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
       	// 执行解析(里面很复杂, 只解析了程序员开发的需要自动配置的类)
        /**
        	candidates 中是主配置类,因为上面有@ComponentScan、和 @EnableAutoConfiguration 所以执行了
        	基包下类的解析和 MEDA-INFO/spring.factories 文件中的 EnableAutoConfiguration 类的解析。
        
        	需要解析的类可以分为两种,第一种是程序员自己写的需要自动配置的;第二种是框架默认的,保存在“MEDA-INFO/spring.factories” 中。
        	程序员自己写的,parser 将类解析成 ConfigurationClass 对象,和 BeanDefinition 对象,前者保存在 parser 的
            configurationClasses 属性中,后者 保存(注册)在 beanFactory 的 beanDefinitionMap 属性中。(算是解析完了)。
            框架默认的,parser 只将其解析成 ConfigurationClass 对象,也保存在 parser 的
            configurationClasses 属性中,但还没弄成 beanDefinition。(解析未完成)。
        */
        parser.parse(candidates);
        // 每个需要自动配置的 class 会被解析成 ConfigurationClass 对象,并保存在 parser 中,
        // 这里是校验所有解析到的 ConfigurationClass 对象。(至于怎么校验的,忽略它吧)
        parser.validate();
		
        // 将 parser 解析到的所有 ConfigurationClass 对象拷贝一份到 configClasses,后面要用。
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        // 第一次循环,alreadyParsed 是空的,但如果有第二次、第三次循环 alreadyParsed 就不为空了。
        configClasses.removeAll(alreadyParsed);

        // Read the model and create bean definitions based on its content
        // 上面说道过,configClasses 中一部分已经有了对应的 beanDefinition,一部分还没有。
        // 如果要为没有的那部分新建 beanDefinition,那得先创建个读对象。
        if (this.reader == null) {
            // (看这个名字,都能感觉到它跟创建 BeanDefinition 有关。)
            this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
        }
        // 给 configClasses 中的元素载入 beanDefinition。如果元素有 beanDefinition,那跳过,如果没有就新建。
        this.reader.loadBeanDefinitions(configClasses);
        // 到这里,configClasses 中的元素都已经解析完成了。
        alreadyParsed.addAll(configClasses);
        processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
		// 配置类候选者被解析完了,要清空的,否则后面再添加就说不清楚了。
        candidates.clear();
        /**	
        	这里主要是检查下有没有遗漏的配置类。
        */
        //  只要往 beanDifinitionMap 中添加了新的 beanDefinition,if 判断绝对是成立的。
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            // newCandidateNames:此时 beanDifinitionMap 所有 beanDefinition 的 name。
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            // oldCandidateNames:执行解析前 beanDifinitionMap 所有 beanDefinition 的 name。
            Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
            // alreadyParsedClasses: 保存刚才已经完成解析的所有的 configurationClass 的 name。
            Set<String> alreadyParsedClasses = new HashSet<>();
            // 遍历 alreadyParsed,拿出每个元素的 name 保存到 alreadyParsedClasses。  
            for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            // (真正的检查遗漏要开始了)
            // 遍历全部的 beanDefinition 的 name。	
            for (String candidateName : newCandidateNames) {
                // candidateName 对应的 beanDefinition 不是最初的。
                if (!oldCandidateNames.contains(candidateName)) {
                    // 将这个 beanDefinition 拿出来。
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    // 再判断:(bd 满足配置类条件,但还没有被解析?)
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                        !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        // 如果真是这样,那 bd 就是被遗漏的 beanDefinition 了。要循环一次再将其解析。
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            // 无论循环与否,这个都应该更新。
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());

    // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    // 这里是直接给 beanFactory 中的 singletonObject 属性添加了一个 bean。
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
        sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }
	// 解析完了,清缓存。
    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
        // Clear cache in externally provided MetadataReaderFactory; this is a no-op
        // for a shared cache since it'll be cleared by the ApplicationContext.
        ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
}

到这里 ConfigurationClassPostProcessorprocessConfigBeanDefinitions(BeanDefinitionRegistry registry) 方法的整个执行就梳理完了,至于更细节的东西,下面再写。

这里应该能明白一个问题了:为什么要先执行 processConfigBeanDefinitions() 方法,后执行 postProcessBeanFactory() 方法?

因为后者是修改 beanDefinition 的,而前者是创建 beanDefinition 的。想修改,你得先有个吧。

在 3.2 的代码中,还有几个细节需要再往下走一层,再看看细节:

  1. 怎么判定一个 beanDefinition 是不是满足配置类候选者?
  2. parser.parse(candidates); 方法是怎么解析配置类后选择的?(只送进去一个启动类,结果解析了一大堆)。
  3. this.reader.loadBeanDefinitions(configClasses); 是怎么载入 beanDefinition 的?

他们各自分别对应了一个方法,再往下走一层,看看。

4.ConfigurationClassUtils.checkConfigurationClassCandidate()

/**	ConfigurationClassUtils.java
	检查给定的 beanDefinition 是不是一个配置类的候选者,如果给定的 beanDefinition 是内嵌到配置类(组件类)中的组件类,也要被自动注册的。
*/
public static boolean checkConfigurationClassCandidate(
    BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

    // 获取类名。
    String className = beanDef.getBeanClassName();
    // 类名为空 或者 beanDefinition 中有工厂方法,那么该 beanDefinition 不是配置类的后选择。
    if (className == null || beanDef.getFactoryMethodName() != null) {
        return false;
    }

    // metadata 用来保存既有注解信息,又有类信息。(beanDefinition 保存着 class 的所有信息,当然也包括注解信息。)
    AnnotationMetadata metadata;
	/**
		接下来就是依据配置类的不同形式,获取注解信息。
		这块是我猜的:一个配置类有 基于javaConfig类型的,有使用xml文件的,或者还有其他类型的。
		这些不同形式的配置类都得先翻译 beanDefinition,从而就出现了不同类型的 BeanDefinition。
		所以,下面先判断了给定的 beanDefinition 的类型,再从里面读注解信息。
	*/
    if (beanDef instanceof AnnotatedBeanDefinition &&
        className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
        // Can reuse the pre-parsed metadata from the given BeanDefinition...
        // 被 @SpringBootApplication 注解的启动类的 beanDefinition 属于这种类型。
        metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
    }
    else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
        // Check already loaded Class if present...
        // since we possibly can't even load the class file for this Class.
        Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
        if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
            BeanPostProcessor.class.isAssignableFrom(beanClass) ||
            AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
            EventListenerFactory.class.isAssignableFrom(beanClass)) {
            return false;
        }
        metadata = AnnotationMetadata.introspect(beanClass);
    }
    else {
        try {
            MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
            metadata = metadataReader.getAnnotationMetadata();
        }
        catch (IOException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Could not find class file for introspecting configuration annotations: " +
                             className, ex);
            }
            return false;
        }
    }
    /**
    	执行到这里,注解信息是肯定拿到了,如果拿不到,在上面就返回了。
    	那下面的代码就是要根据注解判断 beanDefinition 是不是配置类候选着。
    */
    // 从 metadata 中拿 @Configuration 注解。
    Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    // 如果能拿到 @Configuration 注解,且 @Configuration 注解中的 proxyBeanMethods 属性值是 true。
    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
        // 配置类设置为 ’full‘模式,对应的 @Configuration(proxyBeanMethods=true)
        // 被注解的类配置类是代理类,调被@Bean注解的方法时,会先去 signclObject 中拿,只有当 signclObject
        // 拿不到时, 执行被@bean注解的方法。所以此模式下,多次拿同一个对象,拿到的都是一样的。
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
        // (这里执行了,下面两个代码块就不会执行了,最后返回 true。说明,有 @configuration 注解,那就是配置类候选者。)
    }
    // 如果拿不到 @Configuration 注解,再判断下 metadata 是不是配置类候选者。
    // 这 ”再判断是找“ 有没有被 @Component、@ComponentScan、@Import、@ImportResource 其中之一注解,
    // 或者有没有被 @Bean注解的方法。如果有,那就是配置类后选择
    else if (config != null || isConfigurationCandidate(metadata)) {
        // 配置类设置为 ’lite‘ 模式,相当于 @Configuration(proxyBeanMethods=false)
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
        // (同样的,被上面 5 个注解其中之一注解的类,也是配置类后选择。)
    }
    else {
        // 否则,那就不是配置类后选择,直接返回 false。
        return false;
    }

    // It's a full or lite configuration candidate... Let's determine the order value, if any.
    // 设置顺序。
    Integer order = getOrder(metadata);
    if (order != null) {
        beanDef.setAttribute(ORDER_ATTRIBUTE, order);
    }
	// 返回 true,表示规定的 beanDefinition 是配置类候选者。
    return true;
}
// ----------------------------------
/** ConfigurationClassUtils.java
	检查给定的 metadata 是不是配置类候选者。
*/
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
    // Do not consider an interface or an annotation...
    // 如果是接口,那就不是配置类候选者,直接返回 false。
    if (metadata.isInterface()) {
        return false;
    }

    // Any of the typical annotations found?
    // 如果被 @Component、@ComponentScan、@Import、@ImportResource 其中之一注解,
    // 那就是配置类候选者,返回 true。
    for (String indicator : candidateIndicators) {
        if (metadata.isAnnotated(indicator)) {
            return true;
        }
    }

    // Finally, let's look for @Bean methods...
    // 如果有被 @Bean 注解的方法,返回 true。否则返回 false。
    return hasBeanMethods(metadata);
}
//-----------------------------------------
private static final Set<String> candidateIndicators = new HashSet<>(8);

static {
    candidateIndicators.add(Component.class.getName());
    candidateIndicators.add(ComponentScan.class.getName());
    candidateIndicators.add(Import.class.getName());
    candidateIndicators.add(ImportResource.class.getName());
}

这个方法就算是梳理完了。简单总结一下:

  1. 被注解@Configuration@Component@ComponentScan@Import@ImportResource 以及 @bean注解了方法 的类都是配置类候选者;
  2. @Configuration(proxyBeanMethods=true) 的配置类是 full模式,除此以外都是 lite 模式。
  3. full模式和 lite 模式的区别:https://blog.csdn.net/demon7552003/article/details/107988310?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242。

5. parse(Set<BeanDefinitionHolder> configCandidates)

这里先要说明一件事情,不然没法往下写。parser() 方法的目的是将配置类解析成 beanDefinition并注册,那入口参数里已经包含了 beanDefinition 了,而且还是已经注册了的,那还解析个什么?

因为 parser 解析的不是入口参数送进来的配置类。 比如入口参数送进来的配置类上有 @Import(Another.class) 注解,那 Another.class 也是要被解析成对应的 beanDefinition 的。再比如入口参数送进来的是启动类,上面有 @ComponentScan 注解,那可是要以启动类所在的包为基包,递推扫描基包目录及其子目录下的所有配置类,为其创建 beanDefinition。

入口参数给的 configCandidates 不过只是个解析的入口而已(而且也应该有个入口),后面要做的事情才是重点。

接下来梳理下 parser 的细节。

/** ConfigurationClassParser.java
	与其说这里是在解析配置类,倒不如说这里是在解析配置类上的注解,并执行注解对应的操作。
*/
public void parse(Set<BeanDefinitionHolder> configCandidates) {
    // 遍历每一个配置类的 BeanDefinitionHolder。
    for (BeanDefinitionHolder holder : configCandidates) {
        // 把 beanDefiniton 拿出来。
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            // (依据 beanDefinition 的类型,执行不同的 parser)
            if (bd instanceof AnnotatedBeanDefinition) {
                // 如果是 AnnotatedBeanDefinition 类型。(启动类就是这种类型)
                parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
            }
            else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
               	// 如果是 AbstractBeanDefinition 类型。
                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);
        }
    }
	// 上面解析的基本都是程序员自己开发的类,通过启动类的 @ComponentScan 注解递归递归基包下的所有配置类。
    //----------------- 分界线 --------------
    // 下面解析的部分框架默认的,那些写在 META-INF/spring.factories 文件中的 EnableAutoConfiguration 的子类,
    // 为什么只解析部分?
    // 因为好些类上都有 @Conditional 注解,只有满足其条件的才能解析那些类。
    //(这个方法我测试了下,具体的细节没有看)
    this.deferredImportSelectorHandler.process();
}

//-------------------------
/** ConfigurationClassParser.java
	很明显,三个 parser 方法虽然入口参数不一样,但是都构建成 ConfigurationClass 对象,
	然后送入 processConfigurationClass() 中执行。
*/
// parse1
protected final void parse(@Nullable String className, String beanName) throws IOException {
    Assert.notNull(className, "No bean class name for configuration class bean definition");
    MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
    processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
}
// parse2
protected final void parse(Class<?> clazz, String beanName) throws IOException {
    processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
}
// parse3
//  启动类会执行这个方法。
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    //  使用 metadata 和 beanName 创建 ConfigurationClass 对象,送到 processConfigurationClass 方法中去解析。
    processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

这里得先说一下大体流程,processConfigurationClass() 方法里面使用了递归,不然看不清楚。在程序刚启动时,configCandidates 肯定是启动类,所以先会走 parse3 方法,因为要扫描基包下的其他组件并解析(在这块会递归),所以在解析其他组件时优惠掉过头来执行 parse1 或者 parse2。

5.1 processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter)

/** ConfigurationClassParser.java
	processConfigurationClass() 主要做流程控制,里面的 doProcessConfigurationClass() 是真正负责解析的。
	记住:当前的代码块是在解析器中。
*/
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    // 判断 configClass 中有没有 @Conditional 注解,并且当前环境是是否满足其条件,如果不满足,那 configClass 不解析。
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
        // 直接返回。
        return;
    }
	/**	
		这块代码主要主判断 configClass 是不是已经被解析了,如果没有还被解析,直接执行后面的代码。
	*/
    // 先从 configurationClasses 中拿一下,看是否能拿到。(如果没有被解析,当然拿不到,所以启动类肯定是从里面拿不到的)
    ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    // 如果已经被解析了
    if (existingClass != null) {
        // 再判断 configClass 是通过 @Import 注解要注册的。
        if (configClass.isImported()) {
            // 如果 existingClass 也是通过 @Import 注解 注册的。
            if (existingClass.isImported()) {
                // 合并两个 ConfigurationClass 对象。
                existingClass.mergeImportedBy(configClass);
            }
            // Otherwise ignore new imported config class; existing non-imported class overrides it.
            // 无论是两者合并,还是值只以 existingClass 为准,到这里 configClass 就被解析完了,直接返回。
            return;
        }
        else {
            // Explicit bean definition found, probably replacing an import.
            // Let's remove the old one and go with the new one.
            // 如果 configClass 不通过 @Import 注解要注册,
            // 那么先得从 configurationClasses 中将 configClass 的信息移除。(因为接下来要重新加进去)
            this.configurationClasses.remove(configClass);
            this.knownSuperclasses.values().removeIf(configClass::equals);
        }
    }
	/**
		接下来要正真开始解析 configClass。使用循环处理 configClass 的超类。
		do{...} 中的 sourceClass 代表超类,如果不为null,那就还需要循环再处理超类,
        超类可能还有超类....., 一直循环处理,直到 sourceClass == null,表示 configClass 解析完了。
        除此以外,doProcessConfigurationClass() 方法内部使用了递归。
	*/
    // Recursively process the configuration class and its superclass hierarchy.
    // SourceClass 类型是对配置类的简单包装,目的是让不同的配置类以统一的方式被调用。
    SourceClass sourceClass = asSourceClass(configClass, filter);
    do {
        sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
    }
    while (sourceClass != null);
	
    // configClass解析完后,构建 configClass:configClass 键值对保存到 configurationClasses 中。
    this.configurationClasses.put(configClass, configClass);
}

这层看完后,肯定还有个疑惑 doProcessConfigurationClass(configClass, sourceClass, filter) 干了嘛啊。去里面看看。

5.2 doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)

前面提到过,送进来的配置类已经是注册了的 beanDefinition ,目下处理的是它上面的其他注解,以及它的父类、接口啥的。到这里可以感觉到 SpringBoot 中的注解,起到了一个“标记” 的功能,当程序启动时,如果看到类上有它“认识”的注解,就执行一段对应的逻辑代码,而不是注解内部写了什么逻辑代码,对被它注解的类执行对应操作。

protected final SourceClass doProcessConfigurationClass(
    ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    throws IOException {

    // 如果有 @Compenent,执行对应的逻辑。
    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) {
            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)) {
                    // 执行了递归,调用 parse1 方法。基包下的每一个满足条件的组件都是需要解析的。
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }

    // Process any @Import annotations
    // 如果有 @Import 注解,执行对应逻辑。
    processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

    // Process any @ImportResource annotations
    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) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // Process default methods on interfaces
    // 处理当前类实现的接口们。
    processInterfaces(configClass, sourceClass);

    // Process superclass, if any
    // 如果有超类,返回超类的 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;
}

这一层就算是“大体”梳理完了,因为 每个注解对应的处理逻辑是怎么样的,这个还没有写。

不过地方已经知道了,如果想看哪个注解的更详细的处理逻辑,建议先去做几个demo,看一些原理相关的资料,有个大体理解过后,再回过头来看对应的源码是怎么走的。

6. 欠账

有两个地方没有写出来:

  1. 每个注解对应的具体执行逻辑还没有写。

  2. META-INFO/spring.factories 文件中默认的 EnableAutoconfiguration 的那些类被加载的具体源码过程,debug 的结果默认的:自动配置的类在前后两个地方被执行过,最终完成了注册。

    • ConfigurationClassPostProcessor.javaparse(Set<BeanDefinitionHolder> configCandidates) 方法中的 this.deferredImportSelectorHandler.process(); 语句
    • ConfigurationClassPostProcessor.javaprocessConfigBeanDefinitions(BeanDefinitionRegistry registry) 方法中的 this.reader.loadBeanDefinitions(configClasses);语句。

    后面补上。

springboot启动报错 "Error creating bean with name" 是一个常见的错误信息,它通常表示在创建 bean(组件)时出现了问题。这个错误信息往往会伴随着更具体的错误信息和堆栈跟踪。 要解决这个问题,你可以尝试以下几个步骤: 1. 检查错误信息:查看完整的错误消息和堆栈跟踪,尤其是在 "Error creating bean with name" 行之后的信息。这些信息可以帮助你确定具体是哪个 bean 出现了问题,以及它的创建过程中可能存在的错误。 2. 检查依赖关系:如果你的 bean 之间存在依赖关系,确保这些依赖项正确配置和注入。检查注入的方式(如 @Autowired、@Resource)是否正确,并确保被依赖的 bean 已经正确定义和初始化。 3. 检查配置文件:如果你在配置文件中定义了 bean,确保配置没有错误,并且与实际代码中的定义一致。检查配置文件的路径、键名、值等,确保没有拼写错误或者其他语法问题。 4. 检查包扫描路径:如果你使用了自动扫描组件的方式(如 @ComponentScan),确保扫描路径正确,并且能够包含到需要创建的 bean。 5. 检查依赖版本:有时候,不同的依赖版本之间可能存在冲突,导致 bean 创建失败。尝试升级或降级相关的依赖版本,以解决可能的冲突问题。 如果以上步骤无法解决问题,建议提供完整的错误信息和代码,以便更准确地定位问题并提供帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值