Spring源码分析(@Configuration)

文章目录

  • 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.AbstractApplicationContextprotected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 委托 PostProcessorRegistrationDelegate 循环执行每个 BeanFactoryPostProcessorPostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// ...
}

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

// org.springframework.context.support.PostProcessorRegistrationDelegatepublic 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 接口的 BeanbeanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

二、processConfigBeanDefinitions

0、整体流程

1)源码分析

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

// org.springframework.context.annotation.ConfigurationClassPostProcessorpublic void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {List<BeanDefinitionHolder> configCandidates = new ArrayList<>();// 遍历容器中的BeanDefinition,获取 configCandidatesString[] 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);}}// 这里获取 configCandidateselse 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) {// 获取 internalConfigurationBeanNameGeneratorBeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);if (generator != null) {this.componentScanBeanNameGenerator = generator;this.importBeanNameGenerator = generator;}}}// 初始化 environmentif (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 循环解析 configCandidatesdo {// 解析 configCandidatesparser.parse(candidates);// 校验 configurationClassesparser.validate();// 移除已解析的,剩下的就是本次解析的Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());configClasses.removeAll(alreadyParsed);// 注册本次解析的 ConfigurationClass 的 BeanDefinitionif (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);// 清空 configCandidatescandidates.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 classesif (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) {// 获取BeanDefinitionBeanDefinition 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.ConfigurationClassUtilspublic 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.ConfigurationClassUtilsprivate 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、@ImportResourcefor (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.ConfigurationClassParserpublic 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.ConfigurationClassParserprotected 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.ConfigurationClassParserprotected 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 {// 处理 @Componentif (configClass.getMetadata().isAnnotated(Component.class.getName())) {// 递归处理当前类的内部类processMemberClasses(configClass, sourceClass, filter);}// 处理 @PropertySourcefor (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(...) }}// 处理 @ComponentScanSet<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());}}}}// 处理 @ImportprocessImports(configClass, sourceClass, getImports(sourceClass), filter, true);// 处理 @ImportResourceAnnotationAttributes 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 recursereturn sourceClass.getSuperClass();}}// 如果没有父类,则返回null,结束外层的do while解析return null;
}

2)@Component 的处理

// org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClassif (configClass.getMetadata().isAnnotated(Component.class.getName())) {// 递归处理当前类的内部类processMemberClasses(configClass, sourceClass, filter);
}
// org.springframework.context.annotation.ConfigurationClassParserprivate void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,Predicate<String> filter) throws IOException {// 获取 memberClassesCollection<SourceClass> memberClasses = sourceClass.getMemberClasses();if (!memberClasses.isEmpty()) {List<SourceClass> candidates = new ArrayList<>(memberClasses.size());// 遍历 memberClasses,添加 configCandidatesfor (SourceClass memberClass : memberClasses) {if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {candidates.add(memberClass);}}// 排序OrderComparator.sort(candidates);// 遍历 configCandidatesfor (SourceClass candidate : candidates) {if (this.importStack.contains(configClass)) {this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));}else {this.importStack.push(configClass);try {// configClass 作为 candidate 的 importedByprocessConfigurationClass(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#doProcessConfigurationClassprocessImports(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.ConfigurationClassParserprivate 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 也不是 ImportBeanDefinitionRegistrarelse {// 按 @Configuration 类处理this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());// configClass 作为 candidate 的 importedByprocessConfigurationClass(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.ConfigurationClassParserpublic void parse(Set<BeanDefinitionHolder> configCandidates) {// 遍历解析...// 处理 DeferredImportSelectorthis.deferredImportSelectorHandler.process();
}

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

3、注册 loadBeanDefinitions

接着看一下 ConfigurationClassBeanDefinitionReaderloadBeanDefinitions 方法。

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

1)源码分析

// org.springframework.context.annotation.ConfigurationClassBeanDefinitionReaderpublic void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();// 遍历加载 parser 解析的 ConfigurationClassfor (ConfigurationClass configClass : configurationModel) {loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);}
}private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {// 判断 @Conditionalif (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.ConfigurationClassPostProcessorpublic 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)) {// ...// 添加到 configBeanDefsconfigBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);}}if (configBeanDefs.isEmpty()) {// nothing to enhance -> return immediatelyreturn;}// 对配置类进行代理的核心类ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {// 需要增强的 BeanDefinitionAbstractBeanDefinition 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 替换为 代理后的classbeanDef.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 替代 默认的DefaultNamingPolicyenhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);// 设置策略 BeanFactoryAwareGeneratorStrategyenhancer.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.ConfigurationClassEnhancerprivate static class BeanFactoryAwareGeneratorStrategy extends ClassLoaderAwareGeneratorStrategy {public BeanFactoryAwareGeneratorStrategy(@Nullable ClassLoader classLoader) {super(classLoader);}@Overrideprotected ClassGenerator transform(ClassGenerator cg) throws Exception {ClassEmitterTransformer transformer = new ClassEmitterTransformer() {@Overridepublic 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.ConfigurationClassEnhancerprivate static final Callback[] CALLBACKS = new Callback[] {new BeanMethodInterceptor(),new BeanFactoryAwareMethodInterceptor(),NoOp.INSTANCE
};

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

1)BeanFactoryAwareMethodInterceptor

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

// org.springframework.context.annotation.ConfigurationClassEnhancerprivate static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {@Overridepublic 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@Nullablepublic 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_FIELDfield.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.ConfigurationClassEnhancerprivate static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {@Overridepublic boolean isMatch(Method candidateMethod) {return (// 第一个条件,不能是Object,这个必定是满足的candidateMethod.getDeclaringClass() != Object.class &&// 第二个条件,不能是setBeanFactory方法(要拦截的方法实际只应该是添加了@Bean注解的方法)!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&// 第三个条件,添加了@Bean注解BeanAnnotationHelper.isBeanAnnotated(candidateMethod));}
}

下面来看一下 intercept 的逻辑

// org.springframework.context.annotation.ConfigurationClassEnhancerprivate static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {@Override@Nullablepublic Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,MethodProxy cglibMethodProxy) throws Throwable {// 获取 beanFactory(之前不是给BEAN_FACTORY_FIELD赋值了吗,这里就是反射获取之前赋的值)ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);// 确定 beanNameString beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);// 判断这个Bean是否是一个域代理的类(存在@Scope注解,并且 proxyMode != NO)if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {beanName = scopedBeanName;}}// 当前Bean 是 FactoryBeanif (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&factoryContainsBean(beanFactory, beanName)) {Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);// ScopedProxyFactoryBeanif (factoryBean instanceof ScopedProxyFactoryBean) {// 不需要进一步代理}// 普通的FactoryBeanelse {// 需要代理其getObject方法,确保通过 beanFactory.getBean(beanName) 创建beanreturn 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.ConfigurationClassEnhancerprivate 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 = falseif (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代表的BeanMethod currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();if (currentlyInvoked != null) {String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);// 注册的就是a跟b的依赖关系,注册到容器中的dependentBeanMap中// key为依赖,value为依赖所在的beanbeanFactory.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.hqwc.cn/news/595818.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Copilot 重新定义Forms表单创建

您好&#xff0c;Microsoft 365 copilot订阅用户&#xff01;很高兴与大家分享&#xff0c;您现在可以在表单中利用 Copilot 更轻松地构建高质量且设计精良的调查、表单和民意调查。 使用 Copilot 重新定义表单创建 只需向 Copilot 描述您想要构建的表单&#xff0c;您就可以…

循环队列的实现及应用——桶排序bucket_sort、基数排序radix_sort

一、循环队列的实现 代码解释 1、完成初始化 2、定义方法 3、测试实例 4、完整代码 class AQueue:def __init__(self, size=10):self.__mSize = sizeself.__front=0self.__rear = 0self.__listArray = [None] * size#清空元素def clear(self):self.__front = 0self.__rear =…

vue 浅解watch cli computed props ref vue slot axios nexttick devtools说明使用

Vue.js 是一个强大的前端框架&#xff0c;它提供了很多有用的功能和工具。你提到的这些特性&#xff08;watch、cli、computed、props、ref、slot、axios、nextTick、devtools&#xff09;在 Vue 中各自扮演着不同的角色。下面我会逐一解释这些特性如何在 Vue 中使用&#xff1…

[StartingPoint][Tier0]Preignition

Task 1 Directory Brute-forcing is a technique used to check a lot of paths on a web server to find hidden pages. Which is another name for this? (i) Local File Inclusion, (ii) dir busting, (iii) hash cracking. (目录暴力破解是一种用于检查 Web 服务器上的大…

数据结构——lesson13排序之计数排序

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

网络网络层之(3)IPv6地址

网络网络层之(3)IPv6协议 Author: Once Day Date: 2024年4月2日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的…

11-LINUX--信号

一.信号的基本概念 信号是系统响应某个条件而产生的事件&#xff0c;进程接收到信号会执行相应的操作。 与信号有关的系统调用在“signal.h”头文件中有声明 常见信号的值&#xff0c;及对应的功能说明&#xff1a; 信号的值在系统源码中的定义如下&#xff1a; 1. #define …

docker容器环境安装记录(MAC M1)(完善中)

0、背景 在MAC M1中搭建商城项目环境时&#xff0c;采用docker统一管理开发工具&#xff0c;期间碰到了许多环境安装问题&#xff0c;做个总结。 1、安装redis 在宿主机新建redis.conf文件运行创建容器命令&#xff0c;进行容器创建、端口映射、文件挂载、以指定配置文件启动…

如何备考2024年AMC10:吃透2000-2023年1250道真题(限时免费送)

2024年AMC10美国数学竞赛还有6个多月就要启动了&#xff0c;那么如何在AMC10比赛中取得好成绩呢&#xff1f;一个被实践的方法是&#xff1a;系统研究和吃透AMC10的历年真题。即使不参加AMC10竞赛&#xff0c;掌握了这些知识和解题思路后初中和高中数学会学得比较轻松、游刃有余…

Spatio-Temporal Pivotal Graph Neural Networks for Traffie Flow Forecasting

摘要:交通流量预测是一个经典的时空数据挖掘问题,具有许多实际应用。,最近,针对该问题提出了各种基于图神经网络(GNN)的方法,并取得了令人印象深刻的预测性能。然而,我们认为大多数现有方法忽视了某些节点(称为关键节点)的重要性,这些节点自然地与多个其他节点表现出…

腾讯云服务器99元一年是真的吗?真的,99元服务器申请入口

腾讯云服务器99元一年是真的吗&#xff1f;真的&#xff0c;99元优惠购买入口 txybk.com/go/99 折合每天8元1个月&#xff0c;腾讯云99元服务器配置为2核2G4M带宽&#xff0c;2024年99元服务器配置最新报价为99元一年&#xff0c;续费也是99元&#xff0c;如下图&#xff1a; …

色彩在设计中的重要性

title: 色彩在设计中的重要性 date: 2024/4/6 19:08:21 updated: 2024/4/6 19:08:21 tags: 色彩心理品牌识别用户体验文化差异创意设计视觉传达易读性 色彩是设计中不可或缺的元素&#xff0c;它不仅可以影响人的情绪和心理状态&#xff0c;还可以在品牌识别、用户体验、文化差…