spring配置文件

fxz大约 69 分钟

spring配置文件

相关类

  • @Configuration:标注在类上,表示该类是个Full模式的配置类。自Spring 5.2.0版本后它加了个proxyBeanMethods属性来显示控制Full模式还是Lite模式,默认是true表示Full模式。
  • @Bean:标注在方法上,表示方法生成一个由Spring容器管理的Bean。
  • ConfigurationClassPostProcessor:用于引导处理@Configuration配置类的后置处理器。注意:它只是引导处理,并不是实际处理。
  • ConfigurationClassUtils:内部工具类。用于判断组件是否是配置类,又或是Full模式/Lite模式,然后在bd元数据里打上标记。它还会处理一件小事:获取@Configuration配置类上标注的@Order排序值并放进bd里。
  • BeanMethod:内部使用的类。用于封装标注有@Bean注解的方法。
  • ConfigurationClass:内部使用的类。每一个@Configuration配置类都会被封装为它,内部会包含多个@Bean方法(BeanMethod)。
  • ConfigurationClassParser:解析@Configuration配置类,最终以ConfigurationClass对象的形式展示,并且填充它:因为一个配置类可以@Import导入另外一个(或者N多个)其它配置类,所以需要填充。
  • ConfigurationClassBeanDefinitionReader:内部使用的类。读取给定的已经解析好的Set<ConfigurationClass>集合,把里面的bd信息注册到BeanDefinitionRegistry里去(这里决定了bd的有序和无序相关问题)。
  • ConfigurationClassEnhancer:内部使用的类。配置类增强器,用于对@Configuration类(Full模式)使用CGLIB增强,生成一个代理子类字节码Class对象。
  • EnhancedConfiguration:被增强器增强过的配置类,都会自动的让实现此接口(实际是个BeanFactoryAware)接口。
  • SpringNamingPolicy:使用CGLIB生成字节码类名名称生成策略 -> 名称中会有BySpringCGLIB字样。
  • BeanFactoryAwareMethodInterceptor:CGLIB代理对象拦截器。作用:拦截代理类的setBeanFactory()方法,给对应属性赋值。
  • BeanMethodInterceptor:CGLIB代理对象拦截器。作用:拦截所有@Bean方法的执行,以支持可以通过直接调用@Bean方法来管理依赖关系(当然也支持FactoryBean模式)。

ConfigurationClassPostProcessor

配置类解析流程

配置类的解析均是交由ConfigurationClassPostProcessor来引导。在Spring Framework里(非Spring Boot)里,它是BeanDefinitionRegistryPostProcessor处理器的唯一实现类,用于引导处理@Configuration配置类。解析入口是postProcessBeanDefinitionRegistry()方法,实际处理委托给了processConfigBeanDefinitions()方法。

ConfigurationClassPostProcessor

从注册进来的配置类(可能是Full模式,可能是Lite模式)里进一步派生bean定义。简而言之:收集到所有的BeanDefinition(后简称为bd)存储起来,包括@Import、@Component等等组件。并且做出标注:是Full模式的还是Lite模式的配置类(若非配置组件就不标注)。

ConfigurationClassPostProcessor@Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        // 生成一个id,放置后面再重复执行
        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);
        }

        // 表示此registry里的bd收集动作,已经做了  避免再重复收集此registry
        this.registriesPostProcessed.add(registryId);

        // 根据配置类,收集到所有的bd信息 并且做出mark标注:是Full模式还是Lite模式,很重要
        processConfigBeanDefinitions(registry);
    }


/**
 * 根据配置类,收集到所有的bd信息 并且做出mark标注:是Full模式还是Lite模式,很重要
 * Build and validate a configuration model based on the registry of
 * {@link Configuration} classes.
 */
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    /**
     * 1. 启动时传入的配置类会注册到容器中 {@link AnnotationConfigApplicationContext#register(Class[])}
     * 2. BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor 里面注册 {@link AbstractApplicationContext#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory)}
     * */
    String[] candidateNames = registry.getBeanDefinitionNames();

    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnabled()) {
              	// Bean 定义已作为配置类进行处理
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        /**
         * 判断是否是配置类
         * 有 @Configuration(proxyBeanMethods=true) full配置类
         * 有 @Configuration(proxyBeanMethods=false) lite配置类
         * 无 @Configuration 但是有  (@Component || @ComponentScan || @Import || @ImportResource || @Bean ) lite配置类
         *
         * 是配置类,还会解析 @Order 注解的值,设置到 BeanDefinition 中。目的是后面配置类排序
         * */
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    //如果未找到@Configuration类,请立即返回
    if (configCandidates.isEmpty()) {
        return;
    }

    /**
     * 通过 Order可以排序,升序排序, order越小越靠前。
     * 可以在配置类上标注 @Order,调整配置类的解析顺序。
     * 升序排列。
     * */
    // Sort by previously determined @Order value, if applicable
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    //检测通过封闭的应用程序上下文提供的任何自定义 Bean 名称生成策略
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            // 可以预先往单例池中添加一个 CONFIGURATION_BEAN_NAME_ GENERATOR的 BeanNameGenerator类型的bean
            // 可以用来作为扫描得到的Bean和 import导入进来的Bean的 beanName
            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();
    }

    // 解析每个@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 {
        StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");

        /**
         * 解析配置类,会把每个 BeanDefinitionHolder 解析为 ConfigurationClass
         * 会解析 @Bean、@Component、@ComponentScan、@ComponentScans、@Import、@ImportResource 也就是会解析出配置类里面的配置类。递归解析
         *
         * 解析完 configClasses,结果是:
         *  1. @Bean 标注的方法,  --> beanMethods属性
         *  2. @ImportResource  --> importedResources属性
         *  3. @Import(ImportBeanDefinitionRegistrar.class)  --> importBeanDefinitionRegistrars属性,后面会回调方法
         *  4. @Import(ImportSelector.class) --> 执行 ImportSelector#selectImports,返回值都解析成配置类
         *  5. @Import() --> 解析成configClass
         *  6. @Import(DeferredImportSelector.class) --> deferredImportSelectorHandler
         *
         *  注:
         *  1. 使用 @Import 导入的类一定是配置类
         *  2. @Import(DeferredImportSelector.class) 会延时解析,SpringBoot 的自动转配 就是通过这个机制实现的。通过延时解析保证 @ConditionalOnXx 注解能正确判断
         */
        parser.parse(candidates); // AppConfig.class ---> BeanDefinition
        parser.validate();

        // configClasses 相当于就是解析之后的结果
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);

        // Read the model and create bean definitions based on its content
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
        }
        /**
         *  【@Bean 第三步】因为解析完的 configClasses 里面会记录 @Bean标注的方法,这个方法被称为 factoryMethod
         *  会在下面的方法注册成 beanDefinition
         */
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);
        processConfig.tag("classCount", () -> String.valueOf(configClasses.size()))
                .end();

        candidates.clear();
        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());

    /**
     * 注册 记录了@Import(A.class)的信息到BeanFactory中,在这里会用到
     * {@link ImportAwareBeanPostProcessor#postProcessBeforeInitialization(Object, String)}
     * */
    // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    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();
    }
}

ConfigurationClassUtils

ConfigurationClassUtils:

/**
*  检查给定的 bean 定义是否是配置类的候选者
 * (或在配置/组件类中声明的嵌套组件类,
 * 也要自动注册),并相应地标记它。
 * @param beanDef 要检查的 bean 定义
 * @param metadataReaderFactory 调用方当前使用的工厂
 * @return 候选人是否有资格成为(任何类型的)配置类
 */
public static boolean checkConfigurationClassCandidate(
       BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

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

    AnnotationMetadata metadata;
    if (beanDef instanceof AnnotatedBeanDefinition &&
          className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
       // Can reuse the pre-parsed metadata from the given 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;
       }
    }

    Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
       // full 配置类
       beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    else if (config != null || isConfigurationCandidate(metadata)) {
       // lite 配置类
       beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {
       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);
    }

    return true;
}

ConfigurationClassParser

ConfigurationClassParser: 

/**
 * 配置类解析
 */
public void parse(Set<BeanDefinitionHolder> configCandidates) {
    for (BeanDefinitionHolder holder : configCandidates) {
        /**
         * 加载完所有的配置类里面的信息。
         * 这里会解析的内容是:
         * 1. @Component
         *      1.1 获取所有的成员内部类 {@link ConfigurationClassParser#processMemberClasses(ConfigurationClass, SourceClass, Predicate)}
         *      1.2 判断是否是配置类 {@link ConfigurationClassUtils#isConfigurationCandidate(AnnotationMetadata)}
         *      1.3 递归解析 {@link ConfigurationClassParser#processConfigurationClass(ConfigurationClass, Predicate)}
         *
         * 2. @PropertySources
         *
         * 3. @ComponentScans、@ComponentScan
         *      3.1 扫描指定包的内容,并注册到IOC容器中 {@link ComponentScanAnnotationParser#parse(AnnotationAttributes, String)}
         *      3.2 判断是否是配置类 {@link ConfigurationClassUtils#checkConfigurationClassCandidate(BeanDefinition, MetadataReaderFactory)}
         *      3.3 是配置类,就解析配置类 {@link ConfigurationClassParser#parse(String, String)}
         *
         * 4. @Import(非DeferredImportSelector的类)    --> 递归调用 {@link ConfigurationClassParser#processConfigurationClass(ConfigurationClass, Predicate)}
         *      处理 @Import(selector.class),最终的结果都是按照配置类来解析 {@link ConfigurationClassParser#processImports(ConfigurationClass, SourceClass, Collection, Predicate, boolean)}
         *      4.1 selector instanceof DeferredImportSelector 。先存起来,这种类型需要延时解析 {@link DeferredImportSelectorHandler#handle(ConfigurationClass, DeferredImportSelector)}
         *      4.2 selector instanceof ImportSelector。递归解析Import {@link ConfigurationClassParser#processImports(ConfigurationClass, SourceClass, Collection, Predicate, boolean)}
         *      4.3 select instanceof ImportBeanDefinitionRegistrar。设置为 configClass 的属性 {@link ConfigurationClass#addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar, AnnotationMetadata)}
         *      4.4 兜底方法,这个就是关键,通过这就能看出 所有@Import导入的类,都会被解析成配置类 {@link ConfigurationClassParser#processConfigurationClass(ConfigurationClass, Predicate)}
         *
         *      可以发现 @Import(DeferredImportSelector.class) 没有立即解析,而是先存起来 带所有配置类解析完之后。在遍历 回调接口方法,递归执行 {@link ConfigurationClassParser#processImports(ConfigurationClass, SourceClass, Collection, Predicate, boolean)}
         *      虽然 @Import(ImportBeanDefinitionRegistrar.class) 也是存起来,但是他是作为 configClass的属性,后面注册BeanDefinition的时候,直接回调方法。不像
         *          @Import(DeferredImportSelector.class) 还会解析回调的结果
         *
         * 6. @ImportResource
         *      设置为 configClass 的属性 {@link ConfigurationClass#addImportedResource(String, Class)}
         *
         * 7. @Bean
         *      设置为 configClass 的属性 {@link ConfigurationClass#addBeanMethod(BeanMethod)}
         *
         * 8. 有父类,且父类含有@Bean方法
         *      8.1 knownSuperclasses.put(superclass, configClass);  记录父类被加载了,避免多个子类是配置类的情况 其父类配置类会被解析多次的问题
         *      8.2 返回父类
         *      8.2 因为是 do...while 执行 {@link ConfigurationClassParser#doProcessConfigurationClass(ConfigurationClass, SourceClass, Predicate)}
         *          所以实现了递归解析配置类的父类
         *      8.3 最终解析的 @Bean 会添加到子类配置类的属性中。比如:
         *          @Configuration
         *          class A extends C {}
         *          @Configuration
         *          class B extends C {}
         *          class C {
         *              @Bean
         *              public A bean(){
         *                  return new A();
         *              }
         *          }
         *
         *          假设 A 比 B 先解析,也就是执行 {@link ConfigurationClassParser#processConfigurationClass(ConfigurationClass, Predicate)}
         *          那么 bean 是属于 A配置类的,不是属于B配置类的
         *
         * */
        BeanDefinition bd = holder.getBeanDefinition();
        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 (BeanDefinitionStoreException ex) {
            throw ex;
        } catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                    "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
        }
    }
    /**
     * 开始解析 @Import(DeferredImportSelector 的实现类)
     * SpringBoot 的自动装配就是通过实现这个接口实现的,目的就是延时加载。因为很多 AutoConfigurationClass 会使用 @ConditionOnMissXx 来判断是否注入bean
     * 所以需要延时加载,才能正确的判断
     * */
    this.deferredImportSelectorHandler.process();
}

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


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) {
			// 该配置类是通过@{@link Import}注册的,或者是由于嵌套在另一个配置类中而自动注册的(比如扫描到的成员内部类是配置类的情况)
            if (configClass.isImported()) {
				// 该配置类是通过@{@link Import}注册的,或者是由于嵌套在另一个配置类中而自动注册的(比如扫描到的成员内部类是配置类的情况)
                if (existingClass.isImported()) {
                    existingClass.mergeImportedBy(configClass);
                }
                // 否则忽略新导入的配置类;现有的非导入类将覆盖它。
                return;
            } else {
                // 找到显式 Bean 定义,可能替换了导入。让我们删除旧的,然后使用新的。
                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values()
                        .removeIf(configClass::equals);
            }
        }

        // 递归处理配置类及其超类层次结构。
        SourceClass sourceClass = asSourceClass(configClass, filter);
        do {
            sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
        } while (sourceClass != null);

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





   /**
     * @param configClass 正在构建的配置类
     * @param sourceClass 一个源类
     * @return 超类,如果未找到或之前未处理,则为 {@code null}
     */
    @Nullable
    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {

        // 配置类有 @Component
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // 处理内部类 是否有配置类
            // Recursively process any member (nested) classes first
            processMemberClasses(configClass, sourceClass, filter);
        }

        // 就是拿到 @PropertySources、@PropertySource 注解
        // Process any @PropertySource annotations
        for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) {
            if (this.environment instanceof ConfigurableEnvironment) {
                /**
                 * 就是将注解对应的资源文件 构造成 PropertySource 类型的对象,并将对象存到 {@link AbstractEnvironment#propertySources} 属性中。
                 *
                 * 使用 `context.getEnvironment().getProperty("name")` 就能读到 资源文件 中定义的内容了
                 * */
                processPropertySource(propertySource);
            } else {
                logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata()
                        .getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        // 会进行扫描,得到的 BeanDefinition会注册到 Spring容器中,并且会检查是不是配置类并进行解析
        // Process any @ComponentScan annotations
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty()
                && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            for (AnnotationAttributes componentScan : componentScans) {
                // 这里就会进行扫描,得到的 BeanDefinition会注册到 Spring容器中
                // 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();
                    }
                    /**
                     * 扫描到的bean,只要有 @Configuration || @Component || @ComponentScan || @Import || @ImportResource || @Bean 方法
                     * 进进行配置类的解析
                     * */
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        // 扫描的结果是配置类,就按照解析配置类的规则解析
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        /**
         * 处理 @Import
         *
         * getImports(sourceClass) 就是拿到类上所有的@Import注解(会递归找)
         * */
        // Process any @Import annotations
        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);
            }
        }

        /**
         *  【@Bean 第一步】处理附加的 @Bean 方法,在这里会把@Bean 标记的方法,先存起来
         * */
        // Process individual @Bean methods
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }
        /**
         * 就是将 sourceClass 的接口递归拿到 @Bean的方法,将方法信息记录到 configClass 中
         * */
        // Process default methods on interfaces
        processInterfaces(configClass, sourceClass);

        /**
         *  【@Bean 第二步】针对父类里面有@Bean的方法,会把已经处理过的父类 存到 knownSuperclasses 这个Map中,避免重复处理
         *  所以但我们使用SpringBoot+SpringMVC的时,注册多个 WebMvcConfigurationSupport 子类时候 发现只有一个子类会生效。就是因为这个机制保证了父类里面的@Bean方法只会被注册一次
         * */
        // Process superclass, if any
        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;
    }


 /**
	 * 注册恰好是配置类本身的成员(嵌套)类。    
	 */
    private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {

        Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
        if (!memberClasses.isEmpty()) {
            List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
            for (SourceClass memberClass : memberClasses) {
                // 内部类 是 配置类
                if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata())
                        && !memberClass.getMetadata()
                        .getClassName()
                        .equals(configClass.getMetadata()
                                .getClassName())) {
                    // 记录一下
                    candidates.add(memberClass);
                }
            }
            OrderComparator.sort(candidates);
            for (SourceClass candidate : candidates) {
                if (this.importStack.contains(configClass)) {
                    this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
                } else {
                    this.importStack.push(configClass);
                    try {
                        /**
                         * 解析配置类。
                         * 记录信息:candidate 的 {@link ConfigurationClass#importedBy} 是  configClass
                         * */
                        processConfigurationClass(candidate.asConfigClass(configClass), filter);
                    } finally {
                        this.importStack.pop();
                    }
                }
            }
        }
    }



 /**
    * 处理给定<code>@PropertySource</code>注释元数据。
     *
     * @param 找到<code>@PropertySource</code>注释的 propertySource 元数据
     * 如果加载属性源失败,则@throws IOException
     */
    private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
        // name
        String name = propertySource.getString("name");
        if (!StringUtils.hasLength(name)) {
            name = null;
        }
        // 编码
        String encoding = propertySource.getString("encoding");
        if (!StringUtils.hasLength(encoding)) {
            encoding = null;
        }
        // 要加载的属性文件
        String[] locations = propertySource.getStringArray("value");
        Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
        // 忽略资源找不到
        boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");

        // 拿到 PropertySourceFactory
        Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
        /**
         * 注:默认是 DefaultPropertySourceFactory ,否则就反射实例化得到 PropertySourceFactory 。
         *     DefaultPropertySourceFactory 不支持解析yml格式的内容,所以要想导入 yml 格式的内容需要自定义。
         *
         * {@link YamlPropertiesFactoryBean#getObject()} 这个是Spring提供的,可解析yml内容成Properties对象,有了Properties对象
         * 就可以构造出 PropertySource 对象
         * */
        PropertySourceFactory factory = (factoryClass
                == PropertySourceFactory.class ? DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));

        // 遍历 locations
        for (String location : locations) {
            try {
                /**
                 * 解析占位符,也就是说可以这么写 @PropertySource("${prop_file}")
                 * */
                String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
                /**
                 * 获取资源文件,这里会处理 classpath: 前缀
                 * {@link GenericApplicationContext#getResource(String)}
                 * {@link DefaultResourceLoader#getResource(String)}
                 * */
                Resource resource = this.resourceLoader.getResource(resolvedLocation);
                /**
                 * 一个 location 对应一个 PropertySource 然后记录到环境变量中 {@link AbstractEnvironment#propertySources}
                 * {@link DefaultPropertySourceFactory#createPropertySource(String, EncodedResource)}
                 *
                 * 注:
                 *  1. name是null,就会根据 EncodedResource 生成名字,默认就是资源文件的路径
                 *  2. 添加的特点是后添加会放到前面
                 * */
                addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
            } catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
                // Placeholders not resolvable or resource not found when trying to open it
                if (ignoreResourceNotFound) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
                    }
                } else {
                    throw ex;
                }
            }
        }
    }


private void addPropertySource(PropertySource<?> propertySource) {
        String name = propertySource.getName();
        MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();

        // 已经添加过了
        if (this.propertySourceNames.contains(name)) {
            // 已经添加过了,那就对已有的属性值进行扩展
            // We've already added a version, we need to extend it
            PropertySource<?> existing = propertySources.get(name);
            if (existing != null) {
                // 拿到新加的 PropertySource
                PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ? ((ResourcePropertySource) propertySource).withResourceName() : propertySource);
                if (existing instanceof CompositePropertySource) {
                    /**
                     * 将新添加的扩展到 现有的里面,newSource 放到集合的前面,从而保证优先使用
                     * */
                    ((CompositePropertySource) existing).addFirstPropertySource(newSource);
                } else {
                    // 将现有的 换成 CompositePropertySource 类型的对象
                    if (existing instanceof ResourcePropertySource) {
                        existing = ((ResourcePropertySource) existing).withResourceName();
                    }
                    CompositePropertySource composite = new CompositePropertySource(name);
                    // newSource 放到集合的前面,从而保证优先使用
                    composite.addPropertySource(newSource);
                    composite.addPropertySource(existing);
                    // 替换掉
                    propertySources.replace(name, composite);
                }
                // 结束
                return;
            }
        }

        if (this.propertySourceNames.isEmpty()) {
            // 添加
            propertySources.addLast(propertySource);
        } else {
            // 拿到最后一个
            String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
            // 放到最后一个之前。也就是说 新添加的的会放在前面
            propertySources.addBefore(firstProcessed, propertySource);
        }
        // 记录
        this.propertySourceNames.add(name);
    }



 private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {

        if (importCandidates.isEmpty()) {
            return;
        }

        if (checkForCircularImports && isChainedImportOnStack(configClass)) {
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
        } else {
            this.importStack.push(configClass);
            try {
                // 遍历所有 @Import的值
                for (SourceClass candidate : importCandidates) {
                    if (candidate.isAssignable(ImportSelector.class)) {
                        // Candidate class is an ImportSelector -> delegate to it to determine imports
                        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);
                        }
                        if (selector instanceof DeferredImportSelector) {
                            this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
                        } else {
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                            processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                        }
                    } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        // Candidate class is an ImportBeanDefinitionRegistrar ->
                        // delegate to it to register additional bean definitions
                        Class<?> candidateClass = candidate.loadClass();
                        ImportBeanDefinitionRegistrar registrar = ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    } else {
                        /**
                         * 兜底,记录导入的类和其对应的元数据
                         * 这个元数据是在 {@link ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor#postProcessBeforeInitialization(Object, String)} 会用到
                         *
                         * 比如:@Import(A.class),是给A.class作为key,value就是元数据
                         * */
                        // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                        // process it as an @Configuration class
                        this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata()
                                .getClassName());
                        /**
                         * 解析配置类。
                         * 记录信息:candidate 的 {@link ConfigurationClass#importedBy} 是  configClass
                         * */
                        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();
            }
        }
    }


 /**
	* 检索所有<code>@Bean</code>方法的元数据。
	*/
    private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
        AnnotationMetadata original = sourceClass.getMetadata();
        Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
        if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
            // Try reading the class file via ASM for deterministic declaration order...
            // Unfortunately, the JVM's standard reflection returns methods in arbitrary
            // order, even between different runs of the same application on the same JVM.
            try {
                AnnotationMetadata asm = this.metadataReaderFactory.getMetadataReader(original.getClassName())
                        .getAnnotationMetadata();
                Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
                if (asmMethods.size() >= beanMethods.size()) {
                    Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
                    for (MethodMetadata asmMethod : asmMethods) {
                        for (MethodMetadata beanMethod : beanMethods) {
                            if (beanMethod.getMethodName()
                                    .equals(asmMethod.getMethodName())) {
                                selectedMethods.add(beanMethod);
                                break;
                            }
                        }
                    }
                    if (selectedMethods.size() == beanMethods.size()) {
                        // All reflection-detected methods found in ASM method set -> proceed
                        beanMethods = selectedMethods;
                    }
                }
            } catch (IOException ex) {
                logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
                // No worries, let's continue with the reflection metadata we started with...
            }
        }
        return beanMethods;
    }


/**
     * 在配置类实现的接口上注册默认方法。
     */
    private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
        // 遍历接口
        for (SourceClass ifc : sourceClass.getInterfaces()) {
            // 接口中有@Bean的方法
            Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
            for (MethodMetadata methodMetadata : beanMethods) {
                // 不是抽象方法,才记录到 configClass 中
                if (!methodMetadata.isAbstract()) {
                    // A default method or other concrete method on a Java 8+ interface...
                    configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
                }
            }
            // 递归处理接口的接口
            processInterfaces(configClass, ifc);
        }
    }

ComponentScanAnnotationParser

ComponentScanAnnotationParser:

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

    Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
    boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
    // 默认为 AnnotationBeanNameGenerator
    scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass));

    ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
        scanner.setScopedProxyMode(scopedProxyMode);
    } else {
        Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
        scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    }

    scanner.setResourcePattern(componentScan.getString("resourcePattern"));

    for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addIncludeFilter(typeFilter);
        }
    }
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addExcludeFilter(typeFilter);
        }
    }

    boolean lazyInit = componentScan.getBoolean("lazyInit");
    if (lazyInit) {
        scanner.getBeanDefinitionDefaults()
                .setLazyInit(true);
    }

    Set<String> basePackages = new LinkedHashSet<>();
    String[] basePackagesArray = componentScan.getStringArray("basePackages");
    for (String pkg : basePackagesArray) {
        String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        Collections.addAll(basePackages, tokenized);
    }
    for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
        basePackages.add(ClassUtils.getPackageName(clazz));
    }
    if (basePackages.isEmpty()) {
        basePackages.add(ClassUtils.getPackageName(declaringClass));
    }

    scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
        @Override
        protected boolean matchClassName(String className) {
            return declaringClass.equals(className);
        }
    });
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}


   /**
     * 包扫描 BeanDefinition
     * 在指定的基础包中执行扫描,
     * 返回已注册的 Bean 定义。
     * <p>此方法<i></i>注册注解配置处理器
     * 而是将此留给调用方。
     *
     * @param basePackages the packages to check for annotated classes
     * @return set of beans registered if any for tooling registration purposes (never {@code null})
     */
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        // 创建bean定义的 holder对象用于保存扫描后生成的bean定义对象
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        // 循环我们的包路径集合
        for (String basePackage : basePackages) {
            // 查找符合条件的 bean
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition candidate : candidates) {
                // 获取 @Scope 的信息
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                candidate.setScope(scopeMetadata.getScopeName());
                // 设置beanName
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                // 处理 @Autowired 相关的
                if (candidate instanceof AbstractBeanDefinition) {
                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                }
                // 处理jsr250相关的组件
                if (candidate instanceof AnnotatedBeanDefinition) {
                    // 解析 @Lazy、@Primary、@DependsOn、@Role、@Description
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }

                // 检查 Spring 容器中是否已经存在该 beanName
                if (checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    /**
                     * 针对 @Scope 进行处理,只要不是 @Scope(proxyMode = ScopedProxyMode.NO | DEFAULT) 就做额外处理。
                     * 具体的处理逻辑是 额外注册一个 BeanDefinition 记录的是原始BeanDefinition,其beanName是 `scopedTarget. + 当前beanName`
                     * 然后返回的是 处理后的BeanDefinition,其实就是修改 beanClass 为 ScopedProxyFactoryBean 这个类型
                     *
                     * {@link ScopedProxyUtils#createScopedProxy(BeanDefinitionHolder, BeanDefinitionRegistry, boolean)}
                     * */
                    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);

                    // 注册到 IOC 容器中
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }

ConfigurationClassBeanDefinitionReader



/**
 *读取 {@code configurationModel},注册 Bean 定义
 * 根据注册表的内容。
 */
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    for (ConfigurationClass configClass : configurationModel) {
        loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}

/**
 * 读取特定的 {@link ConfigurationClass},注册 Bean 定义
 * 用于类本身及其所有 {@link Bean} 方法。
 */
private void loadBeanDefinitionsForConfigurationClass(
        ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

    // 会进行 @Conditional 校验,应该跳过 就不注册到BeanDefinitionMap了
    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;
    }

    // 是通过 @Import 导入的类,或者是成员内部类是配置类的情况
    if (configClass.isImported()) {
        /**
         * 这些配置类比较特殊,还没有注册到BeanFactory中,所以这一步是将这种配置到注册到BeanFactory
         * */
        registerBeanDefinitionForImportedConfigurationClass(configClass);
    }
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
        /**
         *  【@Bean 第四步】将配置类里面的@Bean方法,解析成beanDefinition,然后注册到 beanDefinitionMap 中
         * */
        loadBeanDefinitionsForBeanMethod(beanMethod);
    }

    /**
     * 加载 @ImportResource
     * 会使用  XmlBeanDefinitionReader 进行读取和解析
     * {@link XmlBeanDefinitionReader#loadBeanDefinitions(Resource)}
     * {@link XmlBeanDefinitionReader#doLoadBeanDefinitions(InputSource, Resource)}
     * */
    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

    /**
     *  回调 {@link ImportBeanDefinitionRegistrar#registerBeanDefinitions(AnnotationMetadata, BeanDefinitionRegistry, BeanNameGenerator)}
     *  ioc 容器已经作为入参传入了,你想做啥任你开心
     * */
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}



		/**
     * 将 {@link Configuration} 类本身注册为 Bean 定义。
     */
    private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
        AnnotationMetadata metadata = configClass.getMetadata();
        AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

        // 拿到 @Scope 信息
        ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
        configBeanDef.setScope(scopeMetadata.getScopeName());
        String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
        // 就是将通用的注解值 设置到 BeanDefinition中
        AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
        /**
         * 看看是否需要做 额外处理,和这里是一样的逻辑
         * {@link ClassPathBeanDefinitionScanner#doScan(String...)}
         * */
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        // 注册
        this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
        configClass.setBeanName(configBeanName);

        if (logger.isTraceEnabled()) {
            logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
        }
    }

配置类增强流程

如果一个配置类是Full模式,那么它就需要被CGLIB字节码增强。

增强动作委托给enhanceConfigurationClasses(beanFactory)去完成。

如果是full配置类会使用Cglib生成代理类,然后将代理类覆盖掉原来BeanDefinition记录的beanClass。

ConfigurationClassPostProcessor

/**
* 准备用于在运行时处理 Bean 请求的配置类
 * 将它们替换为 CGLIB 增强的子类。
 */
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    int factoryId = System.identityHashCode(beanFactory);
    // 防止重复处理
    if (this.factoriesPostProcessed.contains(factoryId)) {
        throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + beanFactory);
    }
    this.factoriesPostProcessed.add(factoryId);
    // 在执行postProcessBeanDefinitionRegistry方法的时就已经将
    // 这个id添加到registriesPostProcessed集合中了
    // 所以到这里就不会再重复执行配置类的解析了(解析@Import、@Bean等)
    if (!this.registriesPostProcessed.contains(factoryId)) {
        // BeanDefinitionRegistryPostProcessor 钩子显然不受支持...此时只需延迟调用 processConfigurationClasses。
        processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
    }

    /**
     * 增强配置类class
     */
    enhanceConfigurationClasses(beanFactory);
  
    /**
     * 添加一个后置处理器,用来处理 ImportAware接口、给full配置类设置属性
     * */
    beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}



 /**
	 * 这里就是区别 full配置类 和 lite配置类的地方了。如果是full配置类会使用Cglib生成代理类,然后将代理类覆盖掉原来BeanDefinition记录的beanClass
     * 对 BeanFactory 进行后处理以搜索配置类 BeanDefinitions;
     * 然后,任何候选项都会通过 {@link ConfigurationClassEnhancer} 进行增强。
     * 候选状态由 BeanDefinition 属性元数据确定。
     * @see ConfigurationClassEnhancer
     */
    public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
        StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
        // 记录full配置类
        Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
            BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
            Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
            AnnotationMetadata annotationMetadata = null;
            MethodMetadata methodMetadata = null;
            if (beanDef instanceof AnnotatedBeanDefinition) {
                AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
                annotationMetadata = annotatedBeanDefinition.getMetadata();
                methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
            }
            /**
             * 在这里标记是full配置类还是lite配置类 {@link ConfigurationClassUtils#checkConfigurationClassCandidate(BeanDefinition, MetadataReaderFactory)}
             * */
            if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
                // Configuration class (full or lite) or a configuration-derived @Bean method
                // -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
                // or component class without @Bean methods.
                AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
                if (!abd.hasBeanClass()) {
                    // 是 lite配置类 但是没有 @Bean方法
                    boolean liteConfigurationCandidateWithoutBeanMethods = (
                            ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr)
                                    && annotationMetadata != null
                                    && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
                    if (!liteConfigurationCandidateWithoutBeanMethods) {
                        try {
                            // 记录
                            abd.resolveBeanClass(this.beanClassLoader);
                        } catch (Throwable ex) {
                            throw new IllegalStateException(
                                    "Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
                        }
                    }
                }
            }
            // 是 full 配置类
            if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
                if (!(beanDef instanceof AbstractBeanDefinition)) {
                    throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName
                            + "' since it is not stored in an AbstractBeanDefinition subclass");
                } else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
                    logger.info("Cannot enhance @Configuration bean definition '" + beanName
                            + "' since its singleton instance has been created too early. The typical cause "
                            + "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor "
                            + "return type: Consider declaring such methods as 'static'.");
                }
                // 记录
                configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
            }
        }
        if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
            // nothing to enhance -> return immediately
            enhanceConfigClasses.end();
            return;
        }

        // 这里就是遍历所有的 full配置类,使用cglib生成代理类的class
        ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
        for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
            AbstractBeanDefinition beanDef = entry.getValue();
            // If a @Configuration class gets proxied, always proxy the target class
            beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
            // Set enhanced subclass of the user-specified bean class
            Class<?> configClass = beanDef.getBeanClass();
            /**
             * 这里就是使用cglib生成代理类
             * */
            Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
            if (configClass != enhancedClass) {
                if (logger.isTraceEnabled()) {
                    logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with "
                            + "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
                }
                // 将cglib生成的class 设置到BeanDefinition中
                beanDef.setBeanClass(enhancedClass);
            }
        }
        enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet()
                        .size()))
                .end();
    }

ConfigurationClassEnhancer

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
    // cglib生成的代理类就是会实现 EnhancedConfiguration ,所以这里的目的防止重复代理
    if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("Ignoring request to enhance %s as it has " +
                            "already been enhanced. This usually indicates that more than one " +
                            "ConfigurationClassPostProcessor has been registered (e.g. via " +
                            "<context:annotation-config>). This is harmless, but you may " +
                            "want check your configuration and remove one CCPP if possible",
                    configClass.getName()));
        }
        return configClass;
    }
    /**
     * cglib生成代理类class
     *
     *
     * CallbackFilter是ConditionalCallbackFilter
     *      逻辑很简单
     *          - 是@Bean标注的方法,生成的字节码使用的callback是 BeanMethodInterceptor
     *          - 方法是 setBeanFactory,生成的字节码使用的callback是 BeanFactoryAwareMethodInterceptor
     *
     * Callback是 {@link ConfigurationClassEnhancer#CALLBACKS}
     *      BeanMethodInterceptor
     *      BeanFactoryAwareMethodInterceptor
     *
     * @Bean方法的callback逻辑 {@link BeanMethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}
     * */
    Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
    if (logger.isTraceEnabled()) {
        logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
                configClass.getName(), enhancedClass.getName()));
    }
    return enhancedClass;
}

/**
 * Creates a new CGLIB {@link Enhancer} instance.
 */
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(configSuperClass);
    // 代理类要实现的接口
    enhancer.setInterfaces(new Class<?>[]{EnhancedConfiguration.class});
    enhancer.setUseFactory(false);
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
    // 设置 CallBackFilter,这个是在生成字节码的时候使用filter确定每个生成的方法内使用的callback
    enhancer.setCallbackFilter(CALLBACK_FILTER);
    // 设置 CallBack
    enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
    return enhancer;
}

/**
 * Uses enhancer to generate a subclass of superclass,
 * ensuring that callbacks are registered for the new subclass.
 */
private Class<?> createClass(Enhancer enhancer) {
    Class<?> subclass = enhancer.createClass();
    // Registering callbacks statically (as opposed to thread-local)
    // is critical for usage in an OSGi environment (SPR-5932)...
    Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
    return subclass;
}

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

拦截器执行流程

什么是动态代理?用通俗的话理解就是:代理的核心逻辑就是依赖于拦截器实现的,可见拦截器(也叫增强)之于代理类是何等重要。

上面的三个拦截器中,NoOp.INSTANCE代表什么都没做,因此我们只需要关注前两个。他俩均是MethodInterceptor接口的实现类,均实现了intercept()方法来做具体的拦截操作(他俩均是私有静态内部类哟)。

BeanFactoryAwareMethodInterceptor拦截流程

拦截setBeanFactory()方法的执行

执行时机决定了增强逻辑何时执行,毕竟一般来说都不可能是增强所有的嘛。

我们知道setBeanFactory()方法是由Spring容器在初始化Bean时回调调用的,而代理类实现了EnhancedConfiguration接口(间接实现了BeanFactoryAware接口),所以该拦截器的执行时机为:在Spring初始化代理类实例时执行拦截

作为一个拦截器,增强逻辑才是它的核心。

private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {

        @Override
        @Nullable
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            // 找到本类(代理类)里名为`$$beanFactory`的字段
            // 若没找到直接报错。若找到了此字段,就给此字段赋值
            Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
            Assert.state(field != null, "Unable to find generated BeanFactory field");
            field.set(obj, args[0]);

            // Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
            // If so, call its setBeanFactory() method. If not, just exit.
            // 如果用户类(也就是你自己定义的类)自己实现了该接口,那么别担心,也会给你赋值上
            if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
                return proxy.invokeSuper(obj, args);
            }
            return null;
        }

        @Override
        public boolean isMatch(Method candidateMethod) {
            // 当执行到setBeanFactory(xxx)方法时匹配成功
            return isSetBeanFactory(candidateMethod);
        }

        public static boolean isSetBeanFactory(Method candidateMethod) {
            return (candidateMethod.getName().equals("setBeanFactory") &&
                    candidateMethod.getParameterCount() == 1 &&
                    BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
                    BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
        }
    }

从执行时机知道了,它拦截的是setBeanFactory()方法的执行。所以这里的Method就代表的是setBeanFactory()方法,Object[] args的值是当前容器的BeanFactory工厂(注意理解这句话)实例。

🔥BeanMethodInterceptor拦截流程

拦截任何标注有@Bean注解的方法的调用,以确保正确处理Bean语义,例如作用域(请别忽略它)和AOP代理。

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {

    /**
     * Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
     * existence of this bean object.
     * @throws Throwable as a catch-all for any exception that may be thrown when invoking the
     * super implementation of the proxied method i.e., the actual {@code @Bean} method
     */
    @Override
    @Nullable
    public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
                            MethodProxy cglibMethodProxy) throws Throwable {
        // 拿到 BeanFactory
        ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
        /**
         * 拿到beanName:有@Bean就返回其属性值,是数组只会返回第一个  ->  方法名
         *
         * @Bean({"a", "a2"})
         * @Scope(proxyMode = ScopedProxyMode.NO)
         * public Test a() {
         *     return null;
         * }
         * */
        String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

        // 只要不是 @Scope(proxyMode = ScopedProxyMode.NO) 就是true
        // Determine whether this bean is a scoped-proxy
        if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
            // 拼接上前缀 scopedTarget.
            String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
            if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
                beanName = scopedBeanName;
            }
        }

        // To handle the case of an inter-bean method reference, we must explicitly check the
        // container for already cached instances.

        /**
         * beanName是FactoryBean 且 不是真正创建的bean
         * */
        // First, check to see if the requested bean is a FactoryBean. If so, create a subclass
        // proxy that intercepts calls to getObject() and returns any cached bean instance.
        // This ensures that the semantics of calling a FactoryBean from within @Bean methods
        // is the same as that of referring to a FactoryBean within XML. See SPR-6602.
        if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
                factoryContainsBean(beanFactory, beanName)) {
            // 使用BeanFactory实例化工厂bean
            Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
            if (factoryBean instanceof ScopedProxyFactoryBean) {
                //作用域代理工厂 Bean 是一种特例,不应进一步代理
            } else {
                /**
                 * 使用JDk代理,拦截{@link FactoryBean#getObject()}方法
                 * */
                //它是候选的 FactoryBean - 继续进行增强
                return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
            }
        }

        /**
         * 通过ThreadLocal来记录当前调用的方法,当循环调用@Bean 方法时,第一次是代理对象方法,再调第二次就是执行的父类方法(也就是被代理类的方法)
         * */
        if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
            // The factory is calling the bean method in order to instantiate and register the bean
            // (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
            // create the bean instance.
            if (logger.isInfoEnabled() &&
                    BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
                logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
                                "assignable to Spring's BeanFactoryPostProcessor interface. This will " +
                                "result in a failure to process annotations such as @Autowired, " +
                                "@Resource and @PostConstruct within the method's declaring " +
                                "@Configuration class. Add the 'static' modifier to this method to avoid " +
                                "these container lifecycle issues; see @Bean javadoc for complete details.",
                        beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
            }
            /**
             * enhancedConfigInstance 这个是代理对象
             * invokeSuper 就是反射执行代理对象父类的方法,也就是执行被代理对象方法
             * */
            return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
        }
        /**
         * 解析bean引用。说白了就是从BeanFactory找Bean,单例池中没得就会实例化bean,实例化的时候就会往ThreadLocal记录一下,
         * 然后再执行代理对象的方法进行实例化,也就是会回调到当前方法 {@link BeanMethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}
         * 因为实例化的时候记录了当前方法,所以回调到当前方法满足 isCurrentlyInvokedFactoryMethod 条件,所以就是 super.method 进行实例化
         * */
        return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
    }

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

        // The user (i.e. not the factory) is requesting this bean through a call to
        // the bean method, direct or indirect. The bean may have already been marked
        // as 'in creation' in certain autowiring scenarios; if so, temporarily set
        // the in-creation status to false in order to avoid an exception.
        boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
        try {
            if (alreadyInCreation) {
                beanFactory.setCurrentlyInCreation(beanName, false);
            }
            boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
            if (useArgs && beanFactory.isSingleton(beanName)) {
                // Stubbed null arguments just for reference purposes,
                // expecting them to be autowired for regular singleton references?
                // A safe assumption since @Bean singleton arguments cannot be optional...
                for (Object arg : beanMethodArgs) {
                    if (arg == null) {
                        useArgs = false;
                        break;
                    }
                }
            }
            /**
             * 实例化的时候会标记
             * {@link SimpleInstantiationStrategy#instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object...)}
             * */
            // getBean
            Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
                    beanFactory.getBean(beanName));
            // bean实例和方法返回值类型 不匹配
            if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
                // Detect package-protected NullBean instance through equals(null) check
                if (beanInstance.equals(null)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug(String.format("@Bean method %s.%s called as bean reference " +
                                        "for type [%s] returned null bean; resolving to null value.",
                                beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
                                beanMethod.getReturnType().getName()));
                    }
                    beanInstance = null;
                } else {
                    String msg = String.format("@Bean method %s.%s called as bean reference " +
                                    "for type [%s] but overridden by non-compatible bean instance of type [%s].",
                            beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
                            beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
                    try {
                        BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
                        msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
                    } catch (NoSuchBeanDefinitionException ex) {
                        // Ignore - simply no detailed message then.
                    }
                    // 报错
                    throw new IllegalStateException(msg);
                }
            }
            // 是正在调用的方法,就是在调用@Bean方法
            Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
            if (currentlyInvoked != null) {
                String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
                // 注册依赖关系
                beanFactory.registerDependentBean(beanName, outerBeanName);
            }
            // 返回bean实例
            return beanInstance;
        } finally {
            if (alreadyInCreation) {
                beanFactory.setCurrentlyInCreation(beanName, true);
            }
        }
    }

    @Override
    public boolean isMatch(Method candidateMethod) {
        return (candidateMethod.getDeclaringClass() != Object.class &&
                !BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
                BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
    }

    private ConfigurableBeanFactory getBeanFactory(Object enhancedConfigInstance) {
        // 拿到字段
        Field field = ReflectionUtils.findField(enhancedConfigInstance.getClass(), BEAN_FACTORY_FIELD);
        Assert.state(field != null, "Unable to find generated bean factory field");
        // 拿到字段的值
        Object beanFactory = ReflectionUtils.getField(field, enhancedConfigInstance);
        Assert.state(beanFactory != null, "BeanFactory has not been injected into @Configuration class");
        Assert.state(beanFactory instanceof ConfigurableBeanFactory,
                "Injected BeanFactory is not a ConfigurableBeanFactory");
        return (ConfigurableBeanFactory) beanFactory;
    }

    /**
     * Check the BeanFactory to see whether the bean named <var>beanName</var> already
     * exists. Accounts for the fact that the requested bean may be "in creation", i.e.:
     * we're in the middle of servicing the initial request for this bean. From an enhanced
     * factory method's perspective, this means that the bean does not actually yet exist,
     * and that it is now our job to create it for the first time by executing the logic
     * in the corresponding factory method.
     * <p>Said another way, this check repurposes
     * {@link ConfigurableBeanFactory#isCurrentlyInCreation(String)} to determine whether
     * the container is calling this method or the user is calling this method.
     * @param beanName name of bean to check for
     * @return whether <var>beanName</var> already exists in the factory
     */
    private boolean factoryContainsBean(ConfigurableBeanFactory beanFactory, String beanName) {
        return (beanFactory.containsBean(beanName) && !beanFactory.isCurrentlyInCreation(beanName));
    }

    /**
     * Check whether the given method corresponds to the container's currently invoked
     * factory method. Compares method name and parameter types only in order to work
     * around a potential problem with covariant return types (currently only known
     * to happen on Groovy classes).
     */
    private boolean isCurrentlyInvokedFactoryMethod(Method method) {
        Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
        return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
                Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
    }

    /**
     * Create a subclass proxy that intercepts calls to getObject(), delegating to the current BeanFactory
     * instead of creating a new instance. These proxies are created only when calling a FactoryBean from
     * within a Bean method, allowing for proper scoping semantics even when working against the FactoryBean
     * instance directly. If a FactoryBean instance is fetched through the container via &-dereferencing,
     * it will not be proxied. This too is aligned with the way XML configuration works.
     */
    private Object enhanceFactoryBean(final Object factoryBean, Class<?> exposedType,
                                      final ConfigurableBeanFactory beanFactory, final String beanName) {

        try {
            Class<?> clazz = factoryBean.getClass();
            boolean finalClass = Modifier.isFinal(clazz.getModifiers());
            boolean finalMethod = Modifier.isFinal(clazz.getMethod("getObject").getModifiers());
            // 类是final 或者 getObject方法是final的
            if (finalClass || finalMethod) {
                // 返回值是接口类型才创建代理对象
                if (exposedType.isInterface()) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Creating interface proxy for FactoryBean '" + beanName + "' of type [" +
                                clazz.getName() + "] for use within another @Bean method because its " +
                                (finalClass ? "implementation class" : "getObject() method") +
                                " is final: Otherwise a getObject() call would not be routed to the factory.");
                    }
                    // 使用JDK代理
                    return createInterfaceProxyForFactoryBean(factoryBean, exposedType, beanFactory, beanName);
                } else {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Unable to proxy FactoryBean '" + beanName + "' of type [" +
                                clazz.getName() + "] for use within another @Bean method because its " +
                                (finalClass ? "implementation class" : "getObject() method") +
                                " is final: A getObject() call will NOT be routed to the factory. " +
                                "Consider declaring the return type as a FactoryBean interface.");
                    }
                    return factoryBean;
                }
            }
        } catch (NoSuchMethodException ex) {
            //没有 getObject() 方法 -> 不应该发生,但只要没有人试图调用它......
        }
        return createCglibProxyForFactoryBean(factoryBean, beanFactory, beanName);
    }

    private Object createInterfaceProxyForFactoryBean(final Object factoryBean, Class<?> interfaceType,
                                                      final ConfigurableBeanFactory beanFactory, final String beanName) {

        return Proxy.newProxyInstance(
                factoryBean.getClass().getClassLoader(), new Class<?>[]{interfaceType},
                (proxy, method, args) -> {
                    // 只代理 getObject 方法
                    if (method.getName().equals("getObject") && args == null) {
                        return beanFactory.getBean(beanName);
                    }
                    return ReflectionUtils.invokeMethod(method, factoryBean, args);
                });
    }

    private Object createCglibProxyForFactoryBean(final Object factoryBean,
                                                  final ConfigurableBeanFactory beanFactory, final String beanName) {

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(factoryBean.getClass());
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setCallbackType(MethodInterceptor.class);

        // Ideally create enhanced FactoryBean proxy without constructor side effects,
        // analogous to AOP proxy creation in ObjenesisCglibAopProxy...
        Class<?> fbClass = enhancer.createClass();
        Object fbProxy = null;

        if (objenesis.isWorthTrying()) {
            try {
                fbProxy = objenesis.newInstance(fbClass, enhancer.getUseCache());
            } catch (ObjenesisException ex) {
                logger.debug("Unable to instantiate enhanced FactoryBean using Objenesis, " +
                        "falling back to regular construction", ex);
            }
        }

        if (fbProxy == null) {
            try {
                fbProxy = ReflectionUtils.accessibleConstructor(fbClass).newInstance();
            } catch (Throwable ex) {
                throw new IllegalStateException("Unable to instantiate enhanced FactoryBean using Objenesis, " +
                        "and regular FactoryBean instantiation via default constructor fails as well", ex);
            }
        }

        ((Factory) fbProxy).setCallback(0, (MethodInterceptor) (obj, method, args, proxy) -> {
            if (method.getName().equals("getObject") && args.length == 0) {
                return beanFactory.getBean(beanName);
            }
            return proxy.invoke(factoryBean, args);
        });

        return fbProxy;
    }
}

执行时机:

   			@Override
        public boolean isMatch(Method candidateMethod) {
            return (candidateMethod.getDeclaringClass() != Object.class &&
                    !BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
                    BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
        }

三个条件:

  1. 该方法不能是Object的方法(即使你Object的方法标注了@Bean,我也不认)。
  2. 不能是setBeanFactory()方法。这很容易理解,它交给上个拦截器搞定即可。
  3. 方法必须标注标注有@Bean注解

执行逻辑:

@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
                        MethodProxy cglibMethodProxy) throws Throwable {
    // 拿到 BeanFactory
    ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
    /**
     * 拿到beanName:有@Bean就返回其属性值,是数组只会返回第一个  ->  方法名
     *
     * @Bean({"a", "a2"})
     * @Scope(proxyMode = ScopedProxyMode.NO)
     * public Test a() {
     *     return null;
     * }
     * */
    String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

    // 只要不是 @Scope(proxyMode = ScopedProxyMode.NO) 就是true
    // Determine whether this bean is a scoped-proxy
    if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
        // 拼接上前缀 scopedTarget.
        String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
        if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
            beanName = scopedBeanName;
        }
    }

    // To handle the case of an inter-bean method reference, we must explicitly check the
    // container for already cached instances.

    /**
     * beanName是FactoryBean 且 不是真正创建的bean
     * */
    // First, check to see if the requested bean is a FactoryBean. If so, create a subclass
    // proxy that intercepts calls to getObject() and returns any cached bean instance.
    // This ensures that the semantics of calling a FactoryBean from within @Bean methods
    // is the same as that of referring to a FactoryBean within XML. See SPR-6602.
    if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
            factoryContainsBean(beanFactory, beanName)) {
        // 使用BeanFactory实例化工厂bean
        Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
        if (factoryBean instanceof ScopedProxyFactoryBean) {
            //作用域代理工厂 Bean 是一种特例,不应进一步代理
        } else {
            /**
             * 使用JDk代理,拦截{@link FactoryBean#getObject()}方法
             * */
            //它是候选的 FactoryBean - 继续进行增强
            return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
        }
    }

    /**
     * 通过ThreadLocal来记录当前调用的方法,当循环调用@Bean 方法时,第一次是代理对象方法,再调第二次就是执行的父类方法(也就是被代理类的方法)
     * */
    if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
        // The factory is calling the bean method in order to instantiate and register the bean
        // (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
        // create the bean instance.
        if (logger.isInfoEnabled() &&
                BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
            logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
                            "assignable to Spring's BeanFactoryPostProcessor interface. This will " +
                            "result in a failure to process annotations such as @Autowired, " +
                            "@Resource and @PostConstruct within the method's declaring " +
                            "@Configuration class. Add the 'static' modifier to this method to avoid " +
                            "these container lifecycle issues; see @Bean javadoc for complete details.",
                    beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
        }
        /**
         * enhancedConfigInstance 这个是代理对象
         * invokeSuper 就是反射执行代理对象父类的方法,也就是执行被代理对象方法
         * */
        return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
    }
    /**
     * 解析bean引用。说白了就是从BeanFactory找Bean,单例池中没得就会实例化bean,实例化的时候就会往ThreadLocal记录一下,
     * 然后再执行代理对象的方法进行实例化,也就是会回调到当前方法 {@link BeanMethodInterceptor#intercept(Object, Method, Object[], MethodProxy)}
     * 因为实例化的时候记录了当前方法,所以回调到当前方法满足 isCurrentlyInvokedFactoryMethod 条件,所以就是 super.method 进行实例化
     * */
    return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}



// 创建一个子类代理,拦截对getObject()的调用,委托给当前的BeanFactory
// 而不是创建一个新的实例。这些代理仅在调用FactoryBean时创建
// factoryBean:从容器内拿出来的那个已经存在的工厂Bean实例(是工厂Bean实例)
// exposedType:@Bean标注的方法的返回值类型
private Object enhanceFactoryBean(Object factoryBean, Class<?> exposedType,
		ConfigurableBeanFactory beanFactory, String beanName) {

	try {
		// 看看Spring容器内已经存在的这个工厂Bean的情况,看看是否有final
		Class<?> clazz = factoryBean.getClass();
		boolean finalClass = Modifier.isFinal(clazz.getModifiers());
		boolean finalMethod = Modifier.isFinal(clazz.getMethod("getObject").getModifiers());
		
		// 类和方法其中有一个是final,那就只能看看能不能走接口代理喽
		if (finalClass || finalMethod) {
			// @Bean标注的方法返回值若是接口类型 尝试走基于接口的JDK动态代理
			if (exposedType.isInterface()) {
				// 基于JDK的动态代理
				return createInterfaceProxyForFactoryBean(factoryBean, exposedType, beanFactory, beanName);
			} else {
				// 类或方法存在final情况,但是呢返回类型又不是
				return factoryBean;
			}
		}
	}
	catch (NoSuchMethodException ex) {
		// 没有getObject()方法  很明显,一般不会走到这里
	}
	
	// 到这,说明以上条件不满足:存在final且还不是接口类型
	// 类和方法都不是final,生成一个CGLIB的动态代理
	return createCglibProxyForFactoryBean(factoryBean, beanFactory, beanName);
}

说明:无论是JDK动态代理还是CGLIB的代理实现均非常简单,就是把getObject()方法代理为使用beanFactory.getBean(beanName)去获取实例(要不代理掉的话,每次不就执行你getObject()里面的逻辑了麽,就又会创建新实例啦~)

lite模式和full模式的区别

lite模式:

官方定义为:在没有标注@Configuration的类里面有@Bean方法就称为Lite模式的配置。透过源码再看这个定义是不完全正确的,而应该是有如下case均认为是Lite模式的配置类:

  1. 类上标注有@Component注解
  2. 类上标注有@ComponentScan注解
  3. 类上标注有@Import注解
  4. 类上标注有@ImportResource注解
  5. 若类上没有任何注解,但类内存在@Bean方法

以上case的前提均是类上没有被标注@Configuration,在Spring 5.2之后新增了一种case也算作Lite模式:

标注有@Configuration(proxyBeanMethods = false),注意:此值默认是true哦,需要显示改为false才算是Lite模式。

优点

  • 运行时不再需要给对应类生成CGLIB子类,提高了运行性能,降低了启动时间
  • 可以该配置类当作一个普通类使用喽:也就是说@Bean方法 可以是private、可以是final

缺点

  • 不能声明@Bean之间的依赖,也就是说不能通过方法调用来依赖其它Bean
  • (其实这个缺点还好,很容易用其它方式“弥补”,比如:把依赖Bean放进方法入参里即可)

Full模式:

标注有@Configuration注解的类被称为full模式的配置类。自Spring5.2后这句话改为下面这样我觉得更为精确些:

  • 标注有@Configuration或者@Configuration(proxyBeanMethods = true)的类被称为Full模式的配置类
  • (当然喽,proxyBeanMethods属性的默认值是true,所以一般需要Full模式我们只需要标个注解即可)

优点

  • 可以支持通过常规Java调用相同类的@Bean方法而保证是容器内的Bean,这有效规避了在“Lite模式”下操作时难以跟踪的细微错误。特别对于萌新程序员,这个特点很有意义

缺点

  • 运行时会给该类生成一个CGLIB子类放进容器,有一定的性能、时间开销(这个开销在Spring Boot这种拥有大量配置类的情况下是不容忽视的,这也是为何Spring 5.2新增了proxyBeanMethods属性的最直接原因)
  • 正因为被代理了,所以@Bean方法 不可以是private、不可以是final