Spring源码分析(@Configuration)

news2024/11/18 2:27:39

文章目录

  • Spring源码分析(@Configuration)
  • 一、ConfigurationClassPostProcessor
    • 1、主要作用和特点
    • 2、执行的时机
    • 3、BeanFactoryPostProcessor
    • 4、BeanDefinitionRegistryPostProcessor
    • 5、ConfigurationClassPostProcessor
      • 1)postProcessBeanDefinitionRegistry
      • 2)postProcessBeanFactory
  • 二、processConfigBeanDefinitions
    • 0、整体流程
      • 1)源码分析
      • 2)小结
    • 1、获取配置类候选
      • 1)源码分析
      • 2)小结
    • 2、解析 parse
      • 1)源码分析
      • 2)小结
    • 2.1 processConfigurationClass
    • 2.2 doProcessConfigurationClass(核心)
      • 1)源码分析
      • 2)@Component 的处理
      • 3)@ComponentScan 的处理
      • 4)@Import 的处理
      • 5)小结
    • 2.3 DeferredImportSelector 的处理
    • 3、注册 loadBeanDefinitions
      • 1)源码分析
      • 2)小结
  • 三、enhanceConfigurationClasses
    • 1、增强逻辑
    • 2、策略
    • 3、三个拦截器
      • 1)BeanFactoryAwareMethodInterceptor
      • 2)BeanMethodInterceptor
    • 4、小结

Spring源码分析(@Configuration)

一、ConfigurationClassPostProcessor

ConfigurationClassPostProcessor 是 Spring 框架中的一个后置处理器,主要用于处理带有 @Configuration 注解的配置类。它在 Spring 容器启动时会扫描并解析这些配置类,并进行相关的处理。

1、主要作用和特点

以下是 ConfigurationClassPostProcessor 的主要作用和特点:

  1. 处理配置类:

    主要用于处理带有 @Configuration 注解的配置类。扫描并解析这些配置类,并将其中声明的 Bean 定义注册到容器中。

  2. 支持组件扫描:

    在扫描配置类时,还会处理 @Component@ComponentScan@Import@ImportResource 等注解

  3. 处理@Bean注解:

    对于配置类中使用 @Bean 注解声明的方法,会解析这些方法并将其返回的对象注册为 Spring Bean。

  4. 处理条件注解:

    根据条件注解决定是否注册 Bean。如@ConditionalOnBean@ConditionalOnMissingBean

  5. 处理代理模式:

    在需要使用代理模式的情况下,会对配置类进行处理,确保代理模式的正确使用。

  6. 处理组件依赖:

    会处理配置类之间的依赖关系,确保配置类之间的依赖关系正确解析并注册到容器中。

总的来说,ConfigurationClassPostProcessor 在 Spring 容器启动过程中起着至关重要的作用,它负责扫描、解析和注册带有 @Configuration 注解的配置类,是 Spring 容器实现组件自动装配和依赖注入的重要组成部分。

2、执行的时机

ConfigurationClassPostProcessor 是在 refreshinvokeBeanFactoryPostProcessors 方法中执行的

// org.springframework.context.support.AbstractApplicationContext

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 委托 PostProcessorRegistrationDelegate 循环执行每个 BeanFactoryPostProcessor
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    // ...
}

PostProcessorRegistrationDelegateinvokeBeanFactoryPostProcessors 方法中,重点关注以下内容

// org.springframework.context.support.PostProcessorRegistrationDelegate

public static void invokeBeanFactoryPostProcessors(
    ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // ...
    
    // 循环调用 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

    // 循环调用 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法
    invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    
    // ...
}

在这里插入图片描述

可以看到 currentRegistryProcessorsregistryProcessors 都包含 ConfigurationClassPostProcessor

3、BeanFactoryPostProcessor

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
  • 作用:在容器已经加载了 BeanDefinition 并且实例化了部分 Bean 之后,对已经注册的 Bean 进行进一步的修改、添加或删除。
  • 时机:在 Spring 容器加载了 Bean 定义并实例化了部分 Bean 之后,但在其余 Bean 实例化之前调用。
  • 扩展:开发者可以实现 BeanFactoryPostProcessor 接口来自定义 BeanFactory 的后置处理行为。

4、BeanDefinitionRegistryPostProcessor

// 继承于 BeanFactoryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
  • 作用:在 BeanDefinition 被加载到容器之后、实例化之前,对 BeanDefinition 进行修改、添加或删除。
  • 时机:在 Spring 容器加载 Bean 定义后,但在实例化 Bean 之前调用。
  • 扩展:开发者可以实现 BeanDefinitionRegistryPostProcessor 接口来自定义 BeanDefinition 的注册行为。

5、ConfigurationClassPostProcessor

  • ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor 接口
  • BeanDefinitionRegistryPostProcessor 继承于 BeanFactoryPostProcessor 接口

在这里插入图片描述

因此,ConfigurationClassPostProcessor 是这两个接口的子类,重写了这两个接口的两个方法

  • 先执行 BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry
  • 再执行 BeanFactoryPostProcessorpostProcessBeanFactory

1)postProcessBeanDefinitionRegistry

// org.springframework.context.annotation.ConfigurationClassPostProcessor

/**
 * Derive further bean definitions from the configuration classes in the registry.
 */
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    // 生成一个registryId,防止重复执行
    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);
    }
    // 保存已经执行的registryId,防止重复执行
    this.registriesPostProcessed.add(registryId);
    // 根据配置类,收集到所有的bd信息(也是@Import解析的入口时机,SpringBoot的启动类上也是一个@Configuration)
    processConfigBeanDefinitions(registry);
}

2)postProcessBeanFactory

// org.springframework.context.annotation.ConfigurationClassPostProcessor

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 生成一个factoryId,防止重复执行
    int factoryId = System.identityHashCode(beanFactory);
    // 若重复就抛出异常
    if (this.factoriesPostProcessed.contains(factoryId)) {
        throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
    }
    // 保存已经执行的factoryId,防止重复执行
    this.factoriesPostProcessed.add(factoryId);

    if (!this.registriesPostProcessed.contains(factoryId)) {
        // BeanDefinitionRegistryPostProcessor hook apparently not supported...
        // Simply call processConfigurationClasses lazily at this point then.
        processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
    }

    // 增强配置类(代理的逻辑)
    enhanceConfigurationClasses(beanFactory);

    // 添加后置处理器 ImportAwareBeanPostProcessor
    // 主要用于处理实现了 ImportAware 接口的 Bean
    beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

二、processConfigBeanDefinitions

0、整体流程

1)源码分析

我们先来看一下 processConfigBeanDefinitions 方法的大体实现

// org.springframework.context.annotation.ConfigurationClassPostProcessor

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();

    // 遍历容器中的BeanDefinition,获取 configCandidates
    String[] candidateNames = registry.getBeanDefinitionNames();
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        // 这里获取 configCandidates
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    // 不存在 configCandidates,直接返回
    if (configCandidates.isEmpty()) {
        return;
    }

    // 如果使用了 @Order 注解,就排个序
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    // 初始化 BeanName生成器
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            // 获取 internalConfigurationBeanNameGenerator
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }

    // 初始化 environment
    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }

    // 构建 ConfigurationClassParser,后面 @Configuration 配置类的解析 将委托给这个对象
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    
    // do while 循环解析 configCandidates
    do {
        // 解析 configCandidates
        parser.parse(candidates);

        // 校验 configurationClasses
        parser.validate();

        // 移除已解析的,剩下的就是本次解析的
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);

        // 注册本次解析的 ConfigurationClass 的 BeanDefinition
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
        }
        this.reader.loadBeanDefinitions(configClasses);

        // 添加到已解析列表
        alreadyParsed.addAll(configClasses);

        // 清空 configCandidates
        candidates.clear();
        
        // 检查是否有未解析的配置类,如果有,添加到 candidates 继续执行 do while 循环
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
            Set<String> alreadyParsedClasses = new HashSet<>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            for (String candidateName : newCandidateNames) {
                if (!oldCandidateNames.contains(candidateName)) {
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                        !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());

    // 将 ImportRegistry 注册为bean 以支持 ImportAware @Configuration classes
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
        // IMPORT_REGISTRY_BEAN_NAME = ConfigurationClassPostProcessor.class.getName() + ".importRegistry"
        sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }

    // 清理缓存
    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
        ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
}

2)小结

  1. 遍历容器中的BeanDefinition,获取 configCandidates
  2. 如果使用了 @Order 注解,就排个序
  3. 初始化 BeanName生成器 和 environment
  4. 构建 ConfigurationClassParser,后面 @Configuration 配置类的解析 将委托给这个对象
  5. do while 循环解析 configCandidates
    • 解析: ConfigurationClassParser # parse
    • 注册:ConfigurationClassBeanDefinitionReader # loadBeanDefinitions
  6. 注册 ConfigurationClassPostProcessor.class.getName() + ".importRegistry"
  7. 清理缓存

1、获取配置类候选

1)源码分析

// org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

// 获取并遍历当前容器中所有的BeanDefinitionNames
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
    // 获取BeanDefinition
    BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    // 属性中存在 configurationClass -> 已被当作配置类处理过
    if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
        if (logger.isDebugEnabled()) {
            logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
        }
    }
    // 没有被当作配置类处理过 && 是 Configuration 候选 -> 加入候选列表
    else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
        configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    }
}

// org.springframework.context.annotation.ConfigurationClassUtils

public static boolean checkConfigurationClassCandidate(
    BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

    String className = beanDef.getBeanClassName();
    if (className == null || beanDef.getFactoryMethodName() != null) {
        return false;
    }

    AnnotationMetadata metadata;

    // ...

    // 获取 @Configuration 注解的属性
    Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());

    // proxyBeanMethods = true -> configurationClass = full(代理对象)
    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    // proxyBeanMethods = false -> configurationClass = lite(普通对象)
    else if (config != null || isConfigurationCandidate(metadata)) {
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    // 不是 configuration 候选
    else {
        return false;
    }

    // 走到这里说明是 configuration 候选

    // 如果使用了 @Order 注解,填充 order 属性(后面要排序)
    Integer order = getOrder(metadata);
    if (order != null) {
        beanDef.setAttribute(ORDER_ATTRIBUTE, order);
    }

    return true;
}
// org.springframework.context.annotation.ConfigurationClassUtils

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());
}

public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
    // 不考虑 接口 或 注解
    if (metadata.isInterface()) {
        return false;
    }

    // @Component、@ComponentScan、@Import、@ImportResource
    for (String indicator : candidateIndicators) {
        if (metadata.isAnnotated(indicator)) {
            return true;
        }
    }

    // @Bean 注解声明的方法
    try {
        return metadata.hasAnnotatedMethods(Bean.class.getName());
    }
    catch (Throwable ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
        }
        return false;
    }
}

2)小结

  1. 遍历容器中所有的 BeanDefinition,筛选出 configCandidates。
  2. @Configuration(proxyBeanMethods = true) —> configurationClass = full(代理对象)
  3. @Configuration(proxyBeanMethods = false) 并且满足下列条件 —> configurationClass = lite(普通对象)
    • 不考虑 接口 或 注解
    • 存在 @Component@ComponentScan@Import@ImportResource 中任意注解
    • 存在 @Bean 注解声明的方法
  4. 如果使用了 @Order 注解,填充 order 属性(后面会进行排序)

2、解析 parse

1)源码分析

先来看一下 ConfigurationClassParserparse 方法

// org.springframework.context.annotation.ConfigurationClassParser

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    // 遍历解析
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        // 根据不同的BeanDefinition类型,执行不同的 parse 方法
        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 ...
    }

    // 处理 DeferredImportSelector(SpringBoot自动装配就在这里处理)
    this.deferredImportSelectorHandler.process();
}

不同的 BeanDefinition类型 会执行 不同的 parse 方法,如下所示

// org.springframework.context.annotation.ConfigurationClassParser

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);
}

protected final void parse(Class<?> clazz, String beanName) throws IOException {
    processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
}

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

但是不同的 parse 方法最终都会执行 processConfigurationClass 方法。

2)小结

  • 遍历解析 configCandidates
  • 根据不同的 BeanDefinition 类型,执行不同的 parse 方法(最终都会执行 processConfigurationClass 方法)
  • 处理 DeferredImportSelector
    • SpringBoot 自动装配通过 @Import 引入了 AutoConfigurationImportSelector
    • AutoConfigurationImportSelector 就继承于 DeferredImportSelector
    • 因此 SpringBoot 自动装配 就是在这进行处理的

2.1 processConfigurationClass

// org.springframework.context.annotation.ConfigurationClassParser

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    // 如果当前类使用了@Conditional注解,则需要根据条件判断是否要跳过该类的解析
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
        return;
    }

    // 判断当前类是否已经解析过,防止重复解析
    ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    if (existingClass != null) {
        // @Import重复引入,merge并直接返回
        if (configClass.isImported()) {
            if (existingClass.isImported()) {
                // 合并 ConfigurationClass 的 importedBy 属性(是一个Set集合)
                existingClass.mergeImportedBy(configClass);
            }
            return;
        }
        // 如果不是@Import导入的,说明当前配置类是显式定义的(说明一个类被定义了两次),移除旧的重新解析
        else {
            this.configurationClasses.remove(configClass);
            this.knownSuperclasses.values().removeIf(configClass::equals);
        }
    }

    // 递归处理 configClass 及其父类
    SourceClass sourceClass = asSourceClass(configClass, filter);
    do {
        // 具体的解析(返回当前类型的父类,存在父类,则会循环解析;不存在父类,则返回null退出循环)
        sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
    }
    while (sourceClass != null);

    // 添加到已解析列表
    this.configurationClasses.put(configClass, configClass);
}

可以看到,具体的解析是由 doProcessConfigurationClass 方法完成的。

2.2 doProcessConfigurationClass(核心)

下面看一下 doProcessConfigurationClass 方法,这也是具体处理 Configuration 的核心方法

1)源码分析

// org.springframework.context.annotation.ConfigurationClassParser

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

    // 处理 @Component
    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        // 递归处理当前类的内部类
        processMemberClasses(configClass, sourceClass, filter);
    }

    // 处理 @PropertySource
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), PropertySources.class,
        org.springframework.context.annotation.PropertySource.class)) {

        if (this.environment instanceof ConfigurableEnvironment) {
            // 将指定的配置文件加载到当前Spring环境中。
            processPropertySource(propertySource);
        } else { logger.info(...) }
    }

    // 处理 @ComponentScan
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
        // 判断 @Conditional 注解
        !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            // 根据 @ComponentScan 的参数进行解析,构建 ClassPathBeanDefinitionScanner 进行 doScan 处理
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
            // 检查 scannedBeanDefinitions 以查找任何进一步的配置类,并在需要时递归地进行解析
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                    bdCand = holder.getBeanDefinition();
                }
                // 如果扫描到的BeanDefinition是配置类候选,调用 processConfigurationClass 解析
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }

    // 处理 @Import
    processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

    // 处理 @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);
            // 保存import的资源,后面 loadBeanDefinitions 统一处理
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

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

    // 递归解析接口中的@Bean方法(A default method or other concrete method on a Java 8+ interface)
    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();
        }
    }

    // 如果没有父类,则返回null,结束外层的do while解析
    return null;
}

2)@Component 的处理

// org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    // 递归处理当前类的内部类
    processMemberClasses(configClass, sourceClass, filter);
}
// org.springframework.context.annotation.ConfigurationClassParser

private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
                                  Predicate<String> filter) throws IOException {
    // 获取 memberClasses
    Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
    if (!memberClasses.isEmpty()) {
        List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
        // 遍历 memberClasses,添加 configCandidates
        for (SourceClass memberClass : memberClasses) {
            if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
                !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
                candidates.add(memberClass);
            }
        }
        // 排序
        OrderComparator.sort(candidates);
        // 遍历 configCandidates
        for (SourceClass candidate : candidates) {
            if (this.importStack.contains(configClass)) {
                this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
            }
            else {
                this.importStack.push(configClass);
                try {
                    // configClass 作为 candidate 的 importedBy
                    processConfigurationClass(candidate.asConfigClass(configClass), filter);
                }
                finally {
                    this.importStack.pop();
                }
            }
        }
    }
}

3)@ComponentScan 的处理

// org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

// 解析 @ComponentScan 注解的属性
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
    // 判断 @Conditional 注解
    !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
    // 遍历 @ComponentScan 注解的属性
    for (AnnotationAttributes componentScan : componentScans) {
        // 根据 @ComponentScan 的属性进行解析,构建 ClassPathBeanDefinitionScanner 进行 doScan 处理
        Set<BeanDefinitionHolder> scannedBeanDefinitions =
            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
        // 遍历扫描注册的BeanDefinition,找出其中的配置类候选,并在需要时递归地进行解析
        for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
            BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
            if (bdCand == null) {
                bdCand = holder.getBeanDefinition();
            }
            // 判断 BeanDefinition 是否是 配置类候选
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                // 内部会调用 processConfigurationClass 解析
                parse(bdCand.getBeanClassName(), holder.getBeanName());
            }
        }
    }
}

4)@Import 的处理

先通过getImports方法解析@Import导入的sourceClass,再调用processImports方法进行处理。

// org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

我们先看一下 @Import 注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    /**
	 * {@link Configuration @Configuration}, {@link ImportSelector},
	 * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
	 */
    Class<?>[] value();
}

可以看到该注解可以导入:Configuration、ImportSelector、ImportBeanDefinitionRegistrar、常规的组件类

下面看一下 processImports方法的处理

// org.springframework.context.annotation.ConfigurationClassParser

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 {
            // 循环处理(分为三类进行处理)
            for (SourceClass candidate : importCandidates) {
                // 1. 导入的是 ImportSelector 类型
                if (candidate.isAssignable(ImportSelector.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);
                    }
                    // DeferredImportSelector 类型 --> 放入deferredImportSelectors中,后面统一处理
                    if (selector instanceof DeferredImportSelector) {
                        this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
                    }
                    // 非 DeferredImportSelector 类型 --> 直接调用 selector 的 selectImports 进行处理
                    else {
                        String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                        Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                        processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                    }
                }

                // 2. 导入的是 ImportBeanDefinitionRegistrar 类型
                else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                    Class<?> candidateClass = candidate.loadClass();
                    // 构建 ImportBeanDefinitionRegistrar 实例
                    // 如果是 Aware,还会根据 Aware类型 填充相关属性
                    ImportBeanDefinitionRegistrar registrar =
                        ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
                    // 保存 ImportBeanDefinitionRegistrar 实例,后面 loadBeanDefinitions 统一处理
                    configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                }

                // 3. 既不是 ImportSelector 也不是 ImportBeanDefinitionRegistrar
                else {
                    // 按 @Configuration 类处理
                    this.importStack.registerImport(
                        currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                    // configClass 作为 candidate 的 importedBy
                    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();
        }
    }
}

5)小结

  • 处理 @Component

    • 递归处理当前类的内部类
    • 如果内部类是配置类候选,调用 processConfigurationClass 解析
  • 处理 @PropertySource

    • 将指定的配置文件加载到当前Spring环境中。
  • 处理 @ComponentScan

    • 根据 @ComponentScan 的属性 构建 ClassPathBeanDefinitionScanner 进行 doScan 处理
      • 关于 doScan 的逻辑,可以参考 Spring源码分析(BeanDefinition),这里不再赘述。
    • 如果扫描注册的 BeanDefinition 是配置类候选,调用 processConfigurationClass 解析
  • 处理 @Import:获取 @Import 引入的资源,分为以下三类进行处理

    • ImportSelector 类型:

      • DeferredImportSelector 类型 --> 放入deferredImportSelectors中,后面统一处理
      • 非 DeferredImportSelector 类型 --> 直接调用 selector 的 selectImports 进行处理
    • ImportBeanDefinitionRegistrar 类型:

      • 构建 ImportBeanDefinitionRegistrar 实例(如果是 Aware,还会根据 Aware类型 填充相关属性)

      • 将 构建的实例 暂存到 ConfigurationClassimportBeanDefinitionRegistrars属性

        loadBeanDefinitions 中统一处理。

    • 其他类型:作为 @Configuration 类 处理,调用 processConfigurationClass 解析

  • 处理 @ImportResource

    • 将 引入的资源 暂存到 ConfigurationClassimportedResources属性

      loadBeanDefinitions 中统一处理。

  • 处理 @Bean

    • 将 标记的方法 暂存到 ConfigurationClassbeanMethods属性

      loadBeanDefinitions 中统一处理。

  • 最后 会返回父类(没有父类返回null),用于决定外层 do while 是否需要继续循环处理。

2.3 DeferredImportSelector 的处理

parse 方法的最后,会对 DeferredImportSelector 进行统一的处理

// org.springframework.context.annotation.ConfigurationClassParser

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    // 遍历解析...

    // 处理 DeferredImportSelector
    this.deferredImportSelectorHandler.process();
}

SpringBoot 的自动装配就是在这里进行处理的。具体细节可以参考 SpringBoot源码分析(自动装配),这里不再赘述。

3、注册 loadBeanDefinitions

接着看一下 ConfigurationClassBeanDefinitionReaderloadBeanDefinitions 方法。

其实根据上面的阅读可以发现,前面解析时已经加载了很多BeanDefinition了,但是对于有些情况只做了暂存,没有真正进行加载,而这些后续处理,正是在 ConfigurationClassBeanDefinitionReader # loadBeanDefinitions完成的。

1)源码分析

// org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    // 遍历加载 parser 解析的 ConfigurationClass
    for (ConfigurationClass configClass : configurationModel) {
        loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}

private void loadBeanDefinitionsForConfigurationClass(
    ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

    // 判断 @Conditional
    if (trackedConditionEvaluator.shouldSkip(configClass)) {
        String beanName = configClass.getBeanName();
        if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
            this.registry.removeBeanDefinition(beanName);
        }
        this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
        return;
    }

    // ConfigurationClass 的 importedBy 属性不为空(@Import引入 / @Component的内部类)
    if (configClass.isImported()) {
        registerBeanDefinitionForImportedConfigurationClass(configClass);
    }

    // 遍历 ConfigurationClass 的 beanMethods 属性
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
        // `@Bean`注解标记的方法返回的bean,注册其 `BeanDefinition`
        loadBeanDefinitionsForBeanMethod(beanMethod);
    }

    // 加载 @ImportResource 注解对应的资源
    // 添加的时机:doProcessConfigurationClass -> @ImportResource 的处理
    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

    // 加载 @Import 引入的 ImportBeanDefinitionRegistrar 类型
    // 添加的时机:doProcessConfigurationClass -> @Import 的处理(ImportBeanDefinitionRegistrar 类型)
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

2)小结

遍历加载 parser 解析的 ConfigurationClass

  1. 判断 @Conditional
  2. 注册 @Import 引入的配置类(parse 时填充,这里统一处理)
  3. 加载 @Bean注解标记的方法返回的bean(parse 时填充,这里统一处理)
  4. 加载 @ImportResource注解引入的资源(parse 时填充,这里统一处理)
  5. 加载 @Import注解引入的 ImportBeanDefinitionRegistrar(parse 时填充,这里统一处理)

关于 BeanDefinition 的注册,可以参考 Spring源码分析(BeanDefinition),这里不再赘述。

三、enhanceConfigurationClasses

// org.springframework.context.annotation.ConfigurationClassPostProcessor

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();

    // 获取所有的 BeanDefinitionName 并遍历(已完成 processConfigBeanDefinitions)
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
        BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
        // 获取 configurationClass 属性值
        Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);

        // ...
        
        // 如果 configurationClass = full(需要代理)
        if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
            // ...
            // 添加到 configBeanDefs
            configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
        }
    }

    if (configBeanDefs.isEmpty()) {
        // nothing to enhance -> return immediately
        return;
    }

    // 对配置类进行代理的核心类
    ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
    for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
        // 需要增强的 BeanDefinition
        AbstractBeanDefinition beanDef = entry.getValue();
        // 设置 preserveTargetClass = true,表示使用cglib动态代理
        beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
        // 要代理的类
        Class<?> configClass = beanDef.getBeanClass();
        // 对 full configClass 进行增强 
        Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
        if (configClass != enhancedClass) {
            // logger...
            // 将 BeanDefinition 中的 beanClass 替换为 代理后的class
            beanDef.setBeanClass(enhancedClass);
        }
    }
}

1、增强逻辑

下面看一下 ConfigurationClassEnhancer 中的 enhance 增强方法

// org.springframework.context.annotation.ConfigurationClassEnhancer

// 三个拦截器
private static final Callback[] CALLBACKS = new Callback[] {
    new BeanMethodInterceptor(),
    new BeanFactoryAwareMethodInterceptor(),
    // 代表什么都没做
    NoOp.INSTANCE
};

private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
    // 如果已经实现了EnhancedConfiguration接口,说明被代理过了,直接返回
    if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
        // logger...
        return configClass;
    }
    // 先 newEnhancer 创建一个增强器,然后使用这个增强器生成代理类的Class对象
    Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
    // logger...
    return enhancedClass;
}

private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
    // org.springframework.cglib.proxy.Enhancer
    // 这样可避免在应用程序级别或第三方库和框架上与CGLIB的依赖性发生任何潜在冲突
    Enhancer enhancer = new Enhancer();
    // 被代理的类
    enhancer.setSuperclass(configSuperClass);
    // 代理类实现了 EnhancedConfiguration 接口,EnhancedConfiguration 继承于 BeanFactoryAware 接口
    // 1. 标记作用。如果实现了EnhancedConfiguration,代表已经被代理过了
    // 2. 代理类需要访问BeanFactory,所有实现了BeanFactoryAware接口
    enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
    // 代理类不实现 org.springframework.cglib.proxy.Factory 接口
    enhancer.setUseFactory(false);
    // 使用 SpringNamingPolicy 替代 默认的DefaultNamingPolicy
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    // 设置策略 BeanFactoryAwareGeneratorStrategy
    enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
    // 设置过滤器,CALLBACK_FILTER包含三个拦截器
    enhancer.setCallbackFilter(CALLBACK_FILTER);
    enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
    return enhancer;
}

// 使用增强器生成代理类的字节码对象
private Class<?> createClass(Enhancer enhancer) {
    Class<?> subclass = enhancer.createClass();
    Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
    return subclass;
}

2、策略

// org.springframework.context.annotation.ConfigurationClassEnhancer

private static class BeanFactoryAwareGeneratorStrategy extends ClassLoaderAwareGeneratorStrategy {

    public BeanFactoryAwareGeneratorStrategy(@Nullable ClassLoader classLoader) {
        super(classLoader);
    }

    @Override
    protected ClassGenerator transform(ClassGenerator cg) throws Exception {
        ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
            @Override
            public void end_class() {
                // 这个策略会在代理类中添加一个字段,BEAN_FACTORY_FIELD = "$$beanFactory"
                declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
                super.end_class();
            }
        };
        return new TransformingClassGenerator(cg, transformer);
    }

}

3、三个拦截器

// org.springframework.context.annotation.ConfigurationClassEnhancer

private static final Callback[] CALLBACKS = new Callback[] {
    new BeanMethodInterceptor(),
    new BeanFactoryAwareMethodInterceptor(),
    NoOp.INSTANCE
};

NoOp.INSTANCE 代表什么都没做,我们重点关注前面两个。

1)BeanFactoryAwareMethodInterceptor

BeanFactoryAwareMethodInterceptor 主要拦截 BeanFactoryAware 接口的 setBeanFactory 方法

// org.springframework.context.annotation.ConfigurationClassEnhancer

private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {

    @Override
    public boolean isMatch(Method candidateMethod) {
        // 拦截的是setBeanFactory方法
        return isSetBeanFactory(candidateMethod);
    }

    /**
     * 从前文我们知道,代理类间接实现了 BeanFactoryAware 接口,
     * 因此在创建配置类时,setBeanFactory方法就会被调用,之后就会进入拦截器的intercept方法
     */
    public static boolean isSetBeanFactory(Method candidateMethod) {
        return (candidateMethod.getName().equals("setBeanFactory") &&
                candidateMethod.getParameterCount() == 1 &&
                BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
                BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
    }

    @Override
    @Nullable
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 在生成代理类的字节码时,使用了BeanFactoryAwareGeneratorStrategy策略
        // 这个策略会在代理类中添加一个字段,BEAN_FACTORY_FIELD = "$$beanFactory"

        // 获取字段 BEAN_FACTORY_FIELD = "$$beanFactory"
        Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
        Assert.state(field != null, "Unable to find generated BeanFactory field");

        // 通过反射将 beanFactory 赋值给 BEAN_FACTORY_FIELD
        field.set(obj, args[0]);

        // 如果目标配置类实现了 BeanFactoryAware 接口,则直接调用目标配置类的 setBeanFactory 方法
        if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
            return proxy.invokeSuper(obj, args);
        }

        // 如果目标配置类没有实现 BeanFactoryAware 接口,则直接退出
        return null;
    }
}

2)BeanMethodInterceptor

BeanMethodInterceptor 主要拦截 @Bean 标注的方法。

// org.springframework.context.annotation.ConfigurationClassEnhancer

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
    @Override
    public boolean isMatch(Method candidateMethod) {
        return (
            // 第一个条件,不能是Object,这个必定是满足的
            candidateMethod.getDeclaringClass() != Object.class &&
            // 第二个条件,不能是setBeanFactory方法(要拦截的方法实际只应该是添加了@Bean注解的方法)
            !BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
            // 第三个条件,添加了@Bean注解
            BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
    }
}

下面来看一下 intercept 的逻辑

// org.springframework.context.annotation.ConfigurationClassEnhancer

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
    @Override
    @Nullable
    public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
                            MethodProxy cglibMethodProxy) throws Throwable {
        // 获取 beanFactory(之前不是给BEAN_FACTORY_FIELD赋值了吗,这里就是反射获取之前赋的值)
        ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
        // 确定 beanName
        String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

        // 判断这个Bean是否是一个域代理的类(存在@Scope注解,并且 proxyMode != NO)
        if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
            String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
            if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
                beanName = scopedBeanName;
            }
        }

        // 当前Bean 是 FactoryBean
        if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
            factoryContainsBean(beanFactory, beanName)) {
            Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
            // ScopedProxyFactoryBean
            if (factoryBean instanceof ScopedProxyFactoryBean) {
                // 不需要进一步代理
            }
            // 普通的FactoryBean
            else {
                // 需要代理其getObject方法,确保通过 beanFactory.getBean(beanName) 创建bean
                return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
            }
        }

        // 走到这,说明 当前Bean 不是 FactoryBean

        // 举个例子,假设我们被@Bean标注的是A方法,当前创建的BeanName也是a,这样就符合了这个条件
        // 但是如果是 a(){b()},a方法中使用b方法创建的b对象,那么此时调用b方法创建b对象时,正在执行的是a方法
        // 此时就不满足这个条件,会调用resolveBeanReference方法来处理
        if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
            // logger...

            // 如果 当前执行的方法 就是 拦截的@Bean方法
            return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
        }

        // 如果 当前执行的方法 不是 拦截的@Bean方法。例如a(){b()},拦截的是a(),当前执行的是b()
        return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
    }
}

接着看一下 resolveBeanReference 方法

// org.springframework.context.annotation.ConfigurationClassEnhancer

private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
                                    ConfigurableBeanFactory beanFactory, String beanName) {

    // 判断bean是否正在创建中(在创建Bean之前,会先将Bean标记为正在创建)
    boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
    try {
        // 如果是正在创建的Bean,先将正在创建标记置为false,避免后续调用getBean时报错
        if (alreadyInCreation) {
            beanFactory.setCurrentlyInCreation(beanName, false);
        }
        // @Bean注解标注的方法是否使用参数
        boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
        if (useArgs && beanFactory.isSingleton(beanName)) {
            for (Object arg : beanMethodArgs) {
                // 只要有一个参数为null,useArgs = false
                if (arg == null) {
                    useArgs = false;
                    break;
                }
            }
        }

        // 通过 beanFactory.getBean 获取bean
        // 1. 没有参数 或 存在参数为null -> 调用 getBean(beanName)
        // 2. 存在参数 且 没有参数为null -> 调用 getBean(beanName, beanMethodArgs)
        Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
                               beanFactory.getBean(beanName));

        // getBean返回的类型不是方法返回的类型
        if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
            if (beanInstance.equals(null)) {
                // logger...
                beanInstance = null;
            } else {
                // logger...
                throw new IllegalStateException(msg);
            }
        }

        // currentlyInvoked 就是a(),beanName就是b,outerBeanName就是a
        // currentlyInvoked != null 说明 currentlyInvoked创建的bean 依赖了 beanName代表的Bean
        Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
        if (currentlyInvoked != null) {
            String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
            // 注册的就是a跟b的依赖关系,注册到容器中的dependentBeanMap中
            // key为依赖,value为依赖所在的bean
            beanFactory.registerDependentBean(beanName, outerBeanName);
        }

        return beanInstance;
    }
    
    finally {
        if (alreadyInCreation) {
            // 改回创建中,要走完整个生命周期流程
            beanFactory.setCurrentlyInCreation(beanName, true);
        }
    }
}

4、小结

在 processConfigBeanDefinitions 之后,会执行 enhanceConfigurationClasses

  1. 筛选所有需要代理的配置类
    • 存在 configurationClass 属性(即 @Configuration 修饰)
    • 属性 configurationClass = full(即 @Configuration 的 proxyBeanMethods 属性值为 true,默认即为 true)
  2. 使用 cglib动态代理 进行增强
    • 拦截 BeanFactoryAware 接口的 setBeanFactory 方法,添加属性 "$$beanFactory" 并赋值
    • 拦截 @Bean 标注的方法
      • 处理 FactoryBean 的 getObject 方法,代理为 getBean(ScopedProxyFactoryBean不作处理)
      • 处理 @Bean 标注的方法返回的bean之间的依赖关系

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1573666.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ebpf+perfetto实现调度延迟记录与展示

1.背景 需要分析生产环境的调度问题,如线程的调度延迟有多少,在哪些时间点延迟比较明显,影响其调度的主要原因是什么?其次,我们希望可以比较直观的展示调度延迟情况。最好能对接perfetto的UI和后处理,因为perfetto已经用于分析比较多的性能数据,可以和调度数据进行整合.我们…

聚观早报 | 沃尔沃发布一季度全球销量;苹果将举办财报电话会议

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 4月07日消息 沃尔沃发布一季度全球销量 苹果将举办新财报电话会议 荣耀Magic6支持5.5G通信 特斯拉将建最大超级充…

【计算机网络经典面试题】简述 TCP 三次握手和四次挥手的过程

TCP链接 1.三次挥手2.四次挥手3.拓展说说 TCP 2次握手行不行&#xff1f;为什么要3次 1.三次挥手 1&#xff09;第一次握手&#xff1a;建立连接时&#xff0c;客户端向服务器发送SYN包&#xff08;seqx&#xff09;&#xff0c;请求建立连接&#xff0c;等待确认 2&#xff09…

基于Springboot的Java学习平台

采用技术 基于Springbootjava学习平台的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 系统功能模块 后台管理 用户注册 课程信息 作业信息 资料信息…

【Linux实践室】Linux高级用户管理实战指南:创建与删除用户组操作详解

&#x1f308;个人主页&#xff1a;聆风吟_ &#x1f525;系列专栏&#xff1a;Linux实践室、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️任务描述二. ⛳️相关知识2.1 &#x1f514;Linux创建用户组命令2.1.1 知识点讲解2.1.2…

MacOS Docker 可视化面板 Portainer

一、简介 Portainer 是一个可视化的容器镜像图形管理工具&#xff0c;使用 Portainer 可以轻松构建、管理和维护Docker 环境。 而且完全免费&#xff08;portainer-ce 是免费的&#xff0c;portainer-ee 是需要授权的&#xff0c;今天安装的是 portainer-ce 版本&#xff09;&…

基于51单片机的尾气检测报警器Proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1DBn8A-p6wmP3Zssrrwspyg 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectroni…

Transformer模型-add norm(残差连接归一化)的简明介绍

今天介绍transformer模型的add & norm&#xff08;残差连接&归一化&#xff09; add代表残差连接&#xff08;Residual Connection&#xff09; 残差连接是一种跳过连接,它将输入添加到网络的中间层或输出上。 **残差连接&#xff08;Residual Connection&#xff09;…

深度学习-机器视觉part2

深度学习-机器视觉part2 文章目录 深度学习-机器视觉part2一、从卷积到卷积神经网络二、手撕卷积代码2.1 动机2.2 数据集2.3 卷积操作2.3.1 填充&#xff08;padding&#xff09;2.3.2 卷积块2.3.3 池化2.3.4 Softmax 2.4 完整CNN2.5 训练改进 三、经典CNN模型介绍四、CNN模型的…

SQL Server详细安装使用教程

1.安装环境 现阶段基本不用SQL Server数据库了&#xff0c;看到有这样的分析话题&#xff0c;就把多年前的存货发一下&#xff0c;大家也可以讨论看看&#xff0c;思路上希望还有价值。 SQL Server 2008 R2有32位版本和64位版本&#xff0c;32位版本可以安装在Windows XP及以上…

网络安全之代码签名证书申请

代码签名&#xff0c;作为一种数字安全机制&#xff0c;对于软件开发、分发及用户使用环节具有至关重要的意义。以下从六大方面阐述代码签名必不可少的重要性&#xff1a; 确保代码来源可信&#xff1a; 代码签名如同软件的“身份证”&#xff0c;通过数字证书对开发者身份进…

2024年船舶、海洋工程与应用技术国际学术会议(ICSOEAT 2024)

2024 International Conference on Shipbuilding, Ocean Engineering and Applied Technology ●会议简介 2024年船舶、海洋工程与应用技术国际学术会议&#xff08;ICSOEAT 2024&#xff09;旨在汇聚全球船舶、海洋工程与应用技术领域的专家学者&#xff0c;共同探讨行业前沿…

【话题】程序员35岁会失业吗?

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景招聘分析一、技术更新换代的挑战二、经验与技术的双重优势三、职业发展的多元化选择四、个人成长与职业规划的平衡五、结语文章推荐 背景 35岁被认为是程序员职业生…

【浅尝C++】多态机制=>重载重写隐藏的区别/抽象类/单继承与多继承的虚函数表/多态原理及虚函数表内存存储详谈

&#x1f3e0;专栏介绍&#xff1a;浅尝C专栏是用于记录C语法基础、STL及内存剖析等。 &#x1f3af;每日格言&#xff1a;每日努力一点点&#xff0c;技术变化看得见。 文章目录 多态的概念多态的定义及实现多态的构成条件虚函数虚函数的重写override与final&#xff08;C11&a…

ffmpeg 将多个视频片段合成一个视频

ffmpeg 将多个视频片段合成一个视频 References 网络视频 6 分钟的诅咒。 新建文本文件 filelist.txt filelist.txtfile output_train_video_0.mp4 file output_train_video_1.mp4 file output_train_video_2.mp4 file output_train_video_3.mp4 file output_train_video_4.m…

C语言完结篇(17)

编译和链接 1. 翻译环境和运⾏环境 2. 翻译环境&#xff1a;预编译编译汇编链接 我们知道计算机能够执行的是二进制的指令 而我们的C语言代码都是文本信息 所以我们需要让C语言代码转变为二进制的指令&#xff08;这是需要编译器来进行处理的&#xff09; 翻译环境和运⾏…

2024年MathorCup妈妈杯数学建模思路D题思路解析+参考成品

1 赛题思路 (赛题出来以后第一时间在群内分享&#xff0c;点击下方群名片即可加群) 2 比赛日期和时间 报名截止时间&#xff1a;2024年4月11日&#xff08;周四&#xff09;12:00 比赛开始时间&#xff1a;2024年4月12日&#xff08;周五&#xff09;8:00 比赛结束时间&…

RGB三通道和灰度值的理解

本文都是来自于chatGPT的回答!!! 目录 Q1:像素具有什么属性?Q2:图像的色彩是怎么实现的?Q3:灰度值和颜色值是一个概念吗?Q4:是不是像素具有灰度值&#xff0c;也有三个颜色分量RGB&#xff1f;Q5:灰度图像是没有色彩的吗&#xff1f;Q6: 彩色图像是既具有灰度值也具有RGB三…

Java Spring IoCDI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 前提小知识:高内…