文章目录
- 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
的主要作用和特点:
-
处理配置类:
主要用于处理带有
@Configuration
注解的配置类。扫描并解析这些配置类,并将其中声明的 Bean 定义注册到容器中。 -
支持组件扫描:
在扫描配置类时,还会处理
@Component
、@ComponentScan
、@Import
、@ImportResource
等注解 -
处理@Bean注解:
对于配置类中使用
@Bean
注解声明的方法,会解析这些方法并将其返回的对象注册为 Spring Bean。 -
处理条件注解:
根据条件注解决定是否注册 Bean。如
@ConditionalOnBean
、@ConditionalOnMissingBean
等 -
处理代理模式:
在需要使用代理模式的情况下,会对配置类进行处理,确保代理模式的正确使用。
-
处理组件依赖:
会处理配置类之间的依赖关系,确保配置类之间的依赖关系正确解析并注册到容器中。
总的来说,ConfigurationClassPostProcessor
在 Spring 容器启动过程中起着至关重要的作用,它负责扫描、解析和注册带有 @Configuration
注解的配置类,是 Spring 容器实现组件自动装配和依赖注入的重要组成部分。
2、执行的时机
ConfigurationClassPostProcessor
是在 refresh
的 invokeBeanFactoryPostProcessors
方法中执行的
// org.springframework.context.support.AbstractApplicationContextprotected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 委托 PostProcessorRegistrationDelegate 循环执行每个 BeanFactoryPostProcessorPostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// ...
}
PostProcessorRegistrationDelegate
的 invokeBeanFactoryPostProcessors
方法中,重点关注以下内容
// 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);// ...
}
可以看到 currentRegistryProcessors
和 registryProcessors
都包含 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
是这两个接口的子类,重写了这两个接口的两个方法
- 先执行
BeanDefinitionRegistryPostProcessor
的postProcessBeanDefinitionRegistry
- 再执行
BeanFactoryPostProcessor
的postProcessBeanFactory
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)小结
- 遍历容器中的BeanDefinition,获取 configCandidates
- 如果使用了 @Order 注解,就排个序
- 初始化 BeanName生成器 和 environment
- 构建 ConfigurationClassParser,后面 @Configuration 配置类的解析 将委托给这个对象
- do while 循环解析 configCandidates
- 解析:
ConfigurationClassParser # parse
- 注册:
ConfigurationClassBeanDefinitionReader # loadBeanDefinitions
- 解析:
- 注册
ConfigurationClassPostProcessor.class.getName() + ".importRegistry"
- 清理缓存
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)小结
- 遍历容器中所有的 BeanDefinition,筛选出 configCandidates。
@Configuration(proxyBeanMethods = true)
—> configurationClass = full(代理对象)@Configuration(proxyBeanMethods = false)
并且满足下列条件 —> configurationClass = lite(普通对象)- 不考虑 接口 或 注解
- 存在
@Component
、@ComponentScan
、@Import
、@ImportResource
中任意注解 - 存在
@Bean
注解声明的方法
- 如果使用了
@Order
注解,填充order
属性(后面会进行排序)
2、解析 parse
1)源码分析
先来看一下 ConfigurationClassParser
的 parse
方法
// 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 自动装配 就是在这进行处理的
- 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类型 填充相关属性)
-
将 构建的实例 暂存到
ConfigurationClass
的importBeanDefinitionRegistrars
属性在
loadBeanDefinitions
中统一处理。
-
-
其他类型:作为 @Configuration 类 处理,调用
processConfigurationClass
解析
-
-
处理
@ImportResource
:-
将 引入的资源 暂存到
ConfigurationClass
的importedResources
属性在
loadBeanDefinitions
中统一处理。
-
-
处理
@Bean
:-
将 标记的方法 暂存到
ConfigurationClass
的beanMethods
属性在
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
接着看一下 ConfigurationClassBeanDefinitionReader
的 loadBeanDefinitions
方法。
其实根据上面的阅读可以发现,前面解析时已经加载了很多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
- 判断
@Conditional
- 注册
@Import
引入的配置类(parse 时填充,这里统一处理) - 加载
@Bean
注解标记的方法返回的bean(parse 时填充,这里统一处理) - 加载
@ImportResource
注解引入的资源(parse 时填充,这里统一处理) - 加载
@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
- 筛选所有需要代理的配置类
- 存在 configurationClass 属性(即 @Configuration 修饰)
- 属性 configurationClass = full(即 @Configuration 的 proxyBeanMethods 属性值为 true,默认即为 true)
- 使用 cglib动态代理 进行增强
- 拦截
BeanFactoryAware
接口的setBeanFactory
方法,添加属性"$$beanFactory"
并赋值 - 拦截
@Bean
标注的方法- 处理 FactoryBean 的 getObject 方法,代理为 getBean(ScopedProxyFactoryBean不作处理)
- 处理
@Bean
标注的方法返回的bean之间的依赖关系
- 拦截