Spring-ConfigurationClassPostProcessor
呕心沥血的分析了ConfigurationClassPostProcessor的核心源码,深入剖析了Spring注解驱动的原理。对其中的延迟机制、字节码解析优化和代理模型进行了深度的思考,并通过arthas反编译反向验证了full configuration的代理
是Spring 容器中最重要的 BeanFactoryPostProcessor
,它负责解析并处理大量核心注解,其核心职责是:
统一解析所有来源的组件定义(BeanDefinition),并注册到 BeanFactory 中,为后续 Bean 的实例化做好准备。
其处理过程是递归执行的, 每当发现新的配置类、新的导入组件或扫描结果,它都会再次触发处理,直到不再有新组件为止。也就是说,新解析出的类本身也可能包含注解配置,需要进一步递归处理。
注解 | 描述 |
---|---|
@Configuration |
标记一个类为配置类,作为入口被首次处理,并会被标记为 full 配置类。 |
@ComponentScan |
扫描指定包路径下的组件类,将扫描到的 @Component 、和元注解中包含 @Component 的注解等注册为 BeanDefinition 。 |
@Import |
导入外部配置类(普通类、ImportSelector ),注册其中定义的 Bean。 |
@ImportResource |
加载 XML 配置文件中的 Bean 定义,与传统的 applicationContext.xml 类似。 |
@Bean |
方法级别的注解,注册方法返回值作为 Bean,由 Spring 容器管理。 |
@PropertySource |
加载外部配置文件(如 .properties ),供 @Value 和 Environment 使用。 |
@Conditional |
根据条件决定是否注册当前配置类或 Bean,贯穿上述所有注解的执行过程。 |
处理BeanDefinition
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 收集所有配置类候选项(Full/Lite)
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 判断这个BeanDefinition是否已经被处理过(只有被处理过才会设置configurationClass属性)
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
/**
* 判断配置类是full(优先判断)还是lite
*
* full: 类上存在@Configuration元注解
*
* lite: 类上存在@Component,@ComponentScan,@Import,@ImportResource元注解。
* 或方法上存在@Bean方法注解
*
*/
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 没有配置类则立即返回
if (configCandidates.isEmpty()) {
return;
}
// bean排序(@Order)
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 创建Full和Lite的解析器
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 {
// 解析Full Configuration和Lite Configuration类(会递归解析)
parser.parse(candidates);
// 解析完成后的校验(@Configuration类的final校验)
parser.validate();
// 获取所有新解析出来的 ConfigurationClass
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());
}
// 将解析出来的 ConfigurationClass 转换为真正的 BeanDefinition 注册到容器中
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
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());
// // 注册 ImportRegistry 用于支持 ImportAware 的功能
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
解析BeanDefinition
ConfigurationClassParser#doProcessConfigurationClass
真正解析Configuration Class的工具类(真正的解析上面的核心注解),并实现递归解析
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// 1.如果类包含元注解@Component,则递归处理当前类的所有内部类(包括private的)
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}
// 2.处理 @PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
} else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 3.处理@ComponentScan注解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// 执行 @ComponentScan,扫描
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)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 4.处理@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 5.处理 @ImportResource注解
AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),
ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 6.处理有@Bean注解的方法,将这种方法封装为BeanMethod对象并加入beanMethods缓存里,等待后续的处理
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 解析配置类实现的接口中的带有@Bean注解的default方法
processInterfaces(configClass, sourceClass);
// 处理父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// 没有父类或父类已处理完毕,则这个配置类解析完毕
return null;
}
1. 内部类处理(递归处理)
用于处理配置类内部的成员类(例如静态内部类),若其本身也是一个配置类(full 或 lite),则递归进行解析(并使用importStack防止循环依赖解析)。
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
// 获取所有成员类(包括静态/非静态内部类)
Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
if (!memberClasses.isEmpty()) {
List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
for (SourceClass memberClass : memberClasses) {
// 判断该成员类是否是一个有效的配置类(full 或 lite),且不是当前类本身
if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
candidates.add(memberClass);
}
}
// 对候选配置类进行排序,排序依据可能是 @Order 注解或实现 Ordered 接口
OrderComparator.sort(candidates);
// 逐个处理符合条件的成员配置类
for (SourceClass candidate : candidates) {
// 检查 import 栈中是否存在当前 configClass,防止循环 import 导致死递归
if (this.importStack.contains(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
// 将当前配置类推入 import 栈,准备递归处理内部类
this.importStack.push(configClass);
try {
// 将该成员类包装成 ConfigurationClass 并递归处理
processConfigurationClass(candidate.asConfigClass(configClass));
}
finally {
// 处理完成后将当前配置类弹出 import 栈
this.importStack.pop();
}
}
}
}
}
2. @PropertySource
将指定的 .properties
配置文件解析并注册到 Spring 的 Environment
中,使配置文件中的属性在应用中可用,并支持如下功能
- 多路径
- 编码设置
- 自定义的
PropertySourceFactory
- 占位符解析
- 是否忽略加载失败的配置文件
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
// 获取 value 属性(属性文件路径),不能为空
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
// 获取是否忽略找不到资源的异常标志
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
// 获取指定的 PropertySourceFactory。默认使用DefaultPropertySourceFactory
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
for (String location : locations) {
try {
// 解析占位符(如 ${user.home}/config.properties)
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
// 加载资源(通常是 classpath 或文件系统路径)
Resource resource = this.resourceLoader.getResource(resolvedLocation);
// 使用 factory 解析资源并加入 Environment 的 PropertySources 中
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
// 根据异常标志判断是否抛异常
if (ignoreResourceNotFound) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
}
else {
throw ex;
}
}
}
}
3. @ComponentScan
注解解析
ComponentScanAnnotationParser#parse方法解析@ComponentScan注解,为后续的真正扫描做准备
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
// 创建 ClassPathBeanDefinitionScanner(包扫描器)
// 默认启用 useDefaultFilters,会注册默认过滤器,只扫描 @Component、@ManagedBean、@Named 等组件
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
// 配置 BeanNameGenerator(用于生成 Bean 的名称)
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(
useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass));
// 处理 @Scope 注解代理方式:ScopedProxyMode
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"));
// 添加 includeFilters(包含过滤器),只匹配指定条件的类
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
// 添加 excludeFilters(排除过滤器),排除不需要的类
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
// 设置默认的懒加载(如果开启,则所有扫描到的 Bean 默认 lazy-init)
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));
}
// 如果未显式指定 basePackages,则默认扫描当前配置类所在的包
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
// 排除当前class,避免source class的重复解析
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
// 准备工作完成,开始扫描
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
扫描
ClassPathBeanDefinitionScanner类开始真正的扫描包(使用ASM而不是反射,避免无用的Class被JVM加载),并进行一系列的过滤以判断是否该纳入容器中。过滤如下
- 需要有**@Component、@ManagedBean、@Named**元注解
- 是具体类(非抽象),或者是抽象类但包含
@Lookup
注解的方法 - excludeFilters(黑名单)和includeFilters(白名单)匹配(excludeFilters优先级更高)
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 至少有1个被扫描的包
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 最终BeanDefinitionHolder合集
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
// 解析 @Scope 作用域元数据(如 singleton、prototype、request 等)
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 对 AbstractBeanDefinition 进行后处理(如设置懒加载、自动注入模式等)
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 处理通用注解(@Lazy、@Primary、@DependsOn、@Role、@Description 等)
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 再次检查BeanDefinition,校验是否重复冲突
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 如果是request、session 等作用域,可能会应用 scoped proxy 代理模式(如 JDK 或 CGLIB)
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder,
this.registry);
beanDefinitions.add(definitionHolder);
// 最终将其注册到 BeanDefinitionRegistry 中(供 Spring 后续实例化使用)
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// 例如扫描site.shanzhao包 -> classpath*:site/shanzhao/**/*.class
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 上述指定路径下的每个class文件将被封装成Resource对象并返回
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
// 不使用反射,使用asm直接将字节码的信息解析出来(包括所有注解(父注解等))
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 对metaData进行判断,是否纳入容器中(@Component、@ManagedBean、@Named判断,@Conditional校验)
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
// 再次校验是否为合法的候选组件(是具体类(非抽象),或者是抽象类但包含 @Lookup 注解的方法)
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
} else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
} else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
}
}
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
} else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
递归
对上述返回的Set集合BeanDefinitionHolder继续full或lite判断,并递归解析其所有的导入情况
// 继续检查这些新扫描的出来的BeanDefinition,递归处理
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
// 递归继续解析新扫描出来的BeanDefinition
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
4. @Import
处理 @Import 注解导入的配置类,是一种显式导入配置类或组件的机制。其相比@ComponentScan,这个注解更轻量和有针对性。它包括以下三类情况
- ImportSelector(
DeferredImportSelector
是其延迟版本,会在所有配置类处理完后统一处理,常用于 Spring Boot 自动配置机制): 动态返回要导入的类名(递归) - ImportBeanDefinitionRegistrar :手动注册 BeanDefinition(不会递归)
- 普通类 :按照配置类继续解析(递归)
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) { // @Import导入为空,就直接返回
return;
}
// 检查是否存在循环导入链,例如 A -> B -> C -> A
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
} else {
// 压栈当前 configClass,防止循环引用
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
// ImportSelector解析(会循环解析)
if (candidate.isAssignable(ImportSelector.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
// aware注入
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (selector instanceof DeferredImportSelector) { // DeferredImportSelector暂不处理(Spring boot用到)
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
} else {
// 普通 ImportSelector 立即执行 selectImports() 获取要导入的类名数组
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
// 递归解析新导入的类
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// ImportBeanDefinitionRegistrar解析
// 不会递归,因为这个接口已经给了BeanDefinitionRegistry,就是让你自由发挥注册BeanDefinition的
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 = BeanUtils.instantiateClass(candidateClass,
ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
// 将 registrar 注册到当前配置类中,后续统一调用
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
} else {
// 其他类型的类(即非 ImportSelector / ImportBeanDefinitionRegistrar)
// 作为普通的 @Configuration 类进行解析处理(可能再次触发 @Import)
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
} 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();
}
}
}
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
if (this.deferredImportSelectors == null) {
// deferredImportSelectors 为 null,说明当前不是“延迟批量处理阶段”,而是递归触发时遇到的
// DeferredImportSelector
// 此时直接单独处理当前这个 DeferredImportSelector,不等到后面统一处理
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
} else {
// deferredImportSelectors 不为 null,说明当前处于“延迟导入收集阶段”,此时仅将当前 holder 暂存下来,后续由
// ConfigurationClassParser#process 统一处理
this.deferredImportSelectors.add(holder);
}
}
5. @ImportResource解析
解析@ImportResource,将解析后得到的数据缓存到ConfigurationClass#importedResources中,等待后续注册BeanDefinition使用
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);
}
}
6. @Bean解析
@Bean注解的解析和缓存,主要步骤总结:
- 使用 ASM 而非反射:通过 ASM 读取类字节码,获取所有
@Bean
方法的有序列表,避免 JVM 反射 API 导致的无序行为 - 封装为 BeanMethod:每个方法会被抽象为
BeanMethod
(包含方法元信息和所属配置类引用)。 - 缓存到 ConfigurationClass:最终这些
BeanMethod
会被缓存到ConfigurationClass#beanMethods
集合中,等到配置类加载完成后由ConfigurationClassBeanDefinitionReader
注册为真正的BeanDefinition
。
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
AnnotationMetadata original = sourceClass.getMetadata();
Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
// 如果 Bean 方法数量大于1 且使用的是基于反射的元数据,尝试使用 ASM 获取确定顺序
if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
try {
// 使用 ASM 从 class 文件中获取元数据(包括方法顺序)
AnnotationMetadata asm = this.metadataReaderFactory.getMetadataReader(original.getClassName())
.getAnnotationMetadata();
Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
// 若 ASM 获取的 @Bean 方法数量 >= 反射获取的,且名字匹配,则使用 ASM 顺序
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())) {
// 保留反射对象,但按 ASM 顺序排列
selectedMethods.add(beanMethod);
break;
}
}
}
// 如果反射获取的所有方法都在 ASM 中找到,则使用 ASM 顺序
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);
// 忽略异常,降级使用反射获取的 Bean 方法集合,虽然顺序不稳定,但逻辑不受影响
}
}
return beanMethods;
}
注册BeanDefinition
ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// @Conditional注解判断(OnBeanCondition会在这发挥作用)
if (trackedConditionEvaluator.shouldSkip(configClass)) {
// 若被跳过且之前已注册过 beanDefinition,则将其移除
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
// 如果是被 @Import 导入的配置类,注册为一个 beanDefinition
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 加载@Bean注解方法的BeanDefinition,并设置使用工厂方法构造
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 处理 @ImportResource 注解导入的 XML 配置文件,注册其中定义的 bean
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// @Import注解(ImportBeanDefinitionRegistrar)的结果注册bean
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
@Bean注册
真正将@Bean方法抽象为ConfigurationClassBeanDefinition并注册到容器中,主要步骤总结:
- 条件匹配判断:若
@Bean
方法上存在@Conditional
,需判断是否应跳过注册 - 确定 Bean 名称与别名
- 构建 BeanDefinition:将方法封装为
ConfigurationClassBeanDefinition
,并设置元数据、作用域、初始化和销毁方法、autowire 策略等属性 - 区分方法类型调用方式
- 静态方法:无需依赖配置类实例,直接通过类调用工厂方法。
- 实例方法:需要通过配置类的 Bean 实例来调用方法(即依赖于配置类自身作为 FactoryBean)。
- 作用域代理支持:若存在
@Scope(proxyMode = ...)
,则通过ScopedProxyCreator
构造代理 BeanDefinition - 注册 BeanDefinition 到容器中:最终调用
registry.registerBeanDefinition()
完成注册。
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
String methodName = metadata.getMethodName();
// @Conditional注解判断是否该跳过
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
// 检查是否存在覆盖(例如 XML ),再根据beanName判断是否抛异常
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
"' clashes with bean name for containing configuration class; please make those names unique!");
}
return;
}
// 构建 BeanDefinition,封装元信息
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
// 使用工厂模式实例化bean:静态方法 or 实例方法
if (metadata.isStatic()) {
// 静态方法直接使用class对象调用
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
} else { // 实例方法要使用FactoryBean对象调用
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
// 设置自动装配模式为构造器注入
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(
org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE,
Boolean.TRUE);
// @Bean方法上的常用注解解析@Lazy等等
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
// 默认就为No
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// 若需要作用域代理(如 request-scoped Bean),则创建代理 BeanDefinition
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
if (logger.isTraceEnabled()) {
logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
// 最终注册 BeanDefinition
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
代理Full Configuration
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
// 记录所有需要增强的配置类
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
// @Configuration类才会被增强(即full configuration class)
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
// 必须是 AbstractBeanDefinition 类型,否则无法增强(不支持自定义 BeanDefinition 实现)
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)) {
// 如果这个 @Configuration Bean 已经被提前实例化,则无法再增强,打印警告日志
// 这种情况通常发生在某些早期调用触发了配置类的提前加载,比如BeanDefinitionRegistryPostProcessor这类bean
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()) {
// 无full则直接返回
return;
}
// 创建配置类增强器
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
try {
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
// 使用ConfigurationClassEnhancer开始增强
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
// 如果增强成功(即 class 被改动了),则更新 beanDefinition 中的 beanClass,用增强后的class来实例化这个bean,而抛弃原class
if (configClass != enhancedClass) {
beanDef.setBeanClass(enhancedClass);
}
}
} catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
ConfigurationClassEnhancer
增强class
// 方法拦截器
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(), // @Bean方法拦截器
new BeanFactoryAwareMethodInterceptor(), // setBeanFactory方法拦截器
NoOp.INSTANCE
};
// 方法拦截器的匹配器,用于匹配class中的具体方法该使用上诉的某个具体拦截器
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
// 增强类内部新增的字段名(类型为BeanFactory)
private static final String BEAN_FACTORY_FIELD = "$$beanFactory";
/**
* 增强后的@Configuration类会实现此接口,既是一种标记,也具备注入BeanFactory的能力
*/
public interface EnhancedConfiguration extends BeanFactoryAware {
}
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
// 判断是否实现了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;
}
// 开始增强
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
return enhancedClass;
}
/**
* 创建CGLIB Enhancer对象并配置参数
*/
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(configSuperClass);
// 设置EnhancedConfiguration接口,这个也实现了BeanFactoryAware接口
// 这样才能获得BeanFactory,让@Bean方法间的调用结果先从BeanFactory中取,维持单例
enhancer.setInterfaces(new Class<?>[] { EnhancedConfiguration.class });
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 自定义生成策略,注入BeanFactory字段(字段名就是$$beanFactory)
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
// 设置拦截器(@Bean方法拦截器和BeanFactoryAware接口里的setBeanFactory方法拦截器)
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
BeanMethodInterceptor
根据其isMatch方法可知其是一个专用于拦截 @Bean 方法调用的 CGLIB 方法拦截器,主要解决了以下两个问题:
- 避免每次调用 @Bean 方法都重复创建 bean 实例
- 支持 @Bean 方法之间的依赖注入(即方法之间互调不再是直接 new,而是走容器获取)
核心执行流程
- 获取BeanFactoryAwareMethodInterceptor设置的BeanFactory
- FactoryBean特殊处理
- 判断是否是工厂方法正在被调用(即二次调用):是为避免通过 getBean(beanName) 自身递归调用,必须直接调用原始方法体(即 super)执行实例化逻辑
- 根据方法的参数,利用BeanFactory真正获取bean(使用的是sourceClass的工厂方法进行实例化)
核心源码
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
// 获取 BeanFactory 实例(通过代理类中的字段注入)
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// 若是作用域代理(如 @Scope(proxyMode = TARGET_CLASS)),需要特殊处理
if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}
// 处理 FactoryBean 的特殊情况
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// Scoped proxy factory beans are a special case and should not be further
// proxied
} else {
// It is a candidate FactoryBean - go ahead with enhancement
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
// 很重要
// 判断当前是否正在通过本方法实例化 bean;如果是,为避免递归代理,直接执行原始方法体(super)创建实例
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
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()));
}
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
// 从 BeanFactory 中解析目标 Bean 的引用,必要时传递参数
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
ConfigurableBeanFactory beanFactory, String beanName) {
boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
try {
// 防止循环依赖死锁:临时将当前 bean 标记为非创建中
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, false);
}
boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
if (useArgs && beanFactory.isSingleton(beanName)) {
for (Object arg : beanMethodArgs) {
if (arg == null) {
useArgs = false;
break;
}
}
}
// 根据参数从容器中获取 Bean
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs)
: beanFactory.getBean(beanName));
// 返回值不匹配,需要抛出异常
if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
// 兼容处理 Spring 的 NullBean
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) {
}
throw new IllegalStateException(msg);
}
}
// 最后再注册依赖关系:当前 bean 被哪个外部工厂方法创建
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
if (currentlyInvoked != null) {
String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
beanFactory.registerDependentBean(beanName, outerBeanName);
}
return beanInstance;
} finally {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, true);
}
}
}
}
BeanFactoryAwareMethodInterceptor
主要的作用是填充$$beanFactory字段
private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
@Nullable
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated BeanFactory field");
// 将BeanFactoryAware接口传来的BeanFactory实例设置到内部新增的$$beanFactory字段上
field.set(obj, args[0]);
// 判断SourceClass是否实现了BeanFactoryAware接口。如果也实现了,则再调用其setBeanFactory方法,将BeanFactory实例设置进去
if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
return proxy.invokeSuper(obj, args);
}
return null;
}
@Override
public boolean isMatch(Method candidateMethod) {
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()));
}
}
arthas反向验证
full class demo
@Configuration
public class ConfigurationClassDemo {
@Bean(initMethod = "initMethod")
public A beanA() {
return new A();
}
@Bean(initMethod = "initMethod")
public B beanB() {
Assert.isTrue(beanA() == beanA(), "impossible error");
return new B();
}
public static class A {
public void initMethod() {
System.out.println("bean A initialized");
}
}
public static class B {
public void initMethod() {
System.out.println("bean B initialized");
}
}
}
arthas反编译后
只保留了关键代码,从反编译后的源码可进行上诉源码分析的验证:
- 实现了ConfigurationClassEnhancer.EnhancedConfiguration接口
- cglib代理,继承了原class
- @Bean方法走的是CGLIB$CALLBACK_0,即BeanMethodInterceptor
- setBeanFactory方法走的是CGLIB$CALLBACK_1,即BeanFactoryAwareMethodInterceptor
- 存在新增的$$beanFactory这个BeanFactory字段
public class ConfigurationClassDemo$$EnhancerBySpringCGLIB$$988746da
extends ConfigurationClassDemo
implements ConfigurationClassEnhancer.EnhancedConfiguration {
// BeanMethodInterceptor
private MethodInterceptor CGLIB$CALLBACK_0;
// BeanFactoryAwareMethodInterceptor
private MethodInterceptor CGLIB$CALLBACK_1;
private NoOp CGLIB$CALLBACK_2;
public BeanFactory $$beanFactory;
public final ConfigurationClassDemo.B beanB() {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
ConfigurationClassDemo$$EnhancerBySpringCGLIB$$988746da.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
return (ConfigurationClassDemo.B)methodInterceptor.intercept(this, CGLIB$beanB$0$Method, CGLIB$emptyArgs, CGLIB$beanB$0$Proxy);
}
return super.beanB();
}
public final ConfigurationClassDemo.A beanA() {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
ConfigurationClassDemo$$EnhancerBySpringCGLIB$$988746da.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
return (ConfigurationClassDemo.A)methodInterceptor.intercept(this, CGLIB$beanA$1$Method, CGLIB$emptyArgs, CGLIB$beanA$1$Proxy);
}
return super.beanA();
}
@Override
public final void setBeanFactory(BeanFactory beanFactory) throws BeansException {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_1;
if (methodInterceptor == null) {
ConfigurationClassDemo$$EnhancerBySpringCGLIB$$988746da.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_1;
}
if (methodInterceptor != null) {
Object object = methodInterceptor.intercept(this, CGLIB$setBeanFactory$6$Method, new Object[]{beanFactory}, CGLIB$setBeanFactory$6$Proxy);
return;
}
super.setBeanFactory(beanFactory);
}
}
总结
- 通过增强 Full 模式的
@Configuration
类,确保@Bean
方法之间的调用不会绕过容器,而是始终返回容器中管理的单例 Bean,避免出现多个实例 - 通过
BeanFactoryAwareMethodInterceptor
拦截器,使增强类持有 BeanFactory 的引用,为后续拦截器中从容器获取 Bean 提供支持 - 通过
BeanMethodInterceptor
拦截器,拦截所有@Bean
方法调用,并通过 BeanFactory 获取对应 Bean,从而确保每次调用返回的都是同一个(单例)实例
总之,Full 模式的增强本质上是让配置类自身也成为容器管理的入口,避免“Java 方法调用”破坏了 Spring 的生命周期和作用域控制
最后
通过整体的源码分析,可知ConfigurationClassPostProcessor是Spring注解驱动的核心,其内部的延迟机制、字节码解析优化和代理模型,是 Spring 保持灵活与健壮性的体现。 最后我再总结以下几个核心的问题
ASM的使用
@ComponentScan
扫描 class 文件时,使用 ASM 而不是反射 来提取类的元数据- ASM 更高效,不会触发类的加载,避免了对未来可能不会用到的类进行 JVM 加载。
- 此阶段 Spring 尚未确定是否要注册这些类为 Bean,因此避免使用反射是出于性能和安全性的双重考量。
@Bean
方法也通过 ASM 解析为MethodMetadata
对象:- 反射获取的方法列表顺序是不确定的,使用 ASM 能保留
@Bean
方法在.class
文件中的定义顺序
- 反射获取的方法列表顺序是不确定的,使用 ASM 能保留
DeferredImportSelector的作用
顾名思义,和延迟相关。是SpringBoot中自动配置的关键,确保了优先解析当前项目中所有的BeanDefinition,以达到覆盖SpringBoot中提供的默认Bean(比如,项目中配置了DataSource的BeanDefinition,这样Springboot提供的DataSourceAutoConfiguration中的DataSource则不会生效)
full configration class的增强
和lite configration class唯一的区别,就是full会被cglib增强,确保@Bean方法始终返回单例bean。所以,可以得出结论,如果配置类不使用 @Bean
方法,只做组件聚合,建议使用 @Component
而非 @Configuration
,可节省 CGLIB 增强开销
@Bean方法拦截获取bean如何避免循环调用
full中@Bean方法会走代理,代理内部会用BeanFactory.getBean()来真正获取bean,获取bean时最终又会走到@Bean代理方法。不怕死循环吗?
其实不用担心,BeanFactory.getBean()来真正获取bean是用工厂方法来创建实例的,调用时会将此方法保存在当前线程的ThreadLocal里(SimpleInstantiationStrategy.currentlyInvokedFactoryMethod字段)。再第二次进入代理时会检查当前方法是否就是调用栈顶部的那个工厂方法,如果是,则绕开代理直接调用 super
方法生成实例。 这一机制确保了代理与容器实例化流程之间协同工作,不会引发死循环