Java 框架 Spring Bean 加载详细过程【源码级逐步分析】
一、核心入口:AbstractAutowireCapableBeanFactory.doCreateBean()
这是 Bean 创建的总调度中心。让我们逐行拆解其核心逻辑(基于 Spring Framework 5.3.x 源码):
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 1. 实例化 Bean (Instantiation)
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// ★ 核心步骤1:创建 Bean 实例 (调用 createBeanInstance)
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// ★ 允许后置处理器修改合并后的 BeanDefinition (MergedBeanDefinitionPostProcessor)
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// ★ 应用 MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
// ... 异常处理
}
mbd.postProcessed = true;
}
}
// ★ 2. 解决循环依赖:提前暴露 Bean 的早期引用 (单例 & 允许循环依赖)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// ★ 将创建 Bean 的 ObjectFactory 加入三级缓存 (singletonFactories)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean; // 最终暴露给外部的对象 (可能是代理对象)
try {
// ★ 3. 属性填充/依赖注入 (Population)
populateBean(beanName, mbd, instanceWrapper);
// ★ 4. 初始化 (Initialization)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
// ... 异常处理
}
// ★ 5. 处理循环依赖的早期引用与最终引用的一致性
if (earlySingletonExposure) {
// 检查是否有其他 Bean 在依赖注入过程中提前通过三级缓存获取了当前 Bean 的早期引用
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 如果初始化后的 exposedObject 与早期引用相同 (通常是没有被 AOP 代理)
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// 如果当前 Bean 依赖了其他 Bean,且那些 Bean 需要用到当前 Bean 的原始版本 (非代理)
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 移除已创建完成的依赖 Bean
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
// ★ 抛出异常:Bean 的最终类型与早期引用类型不一致,可能导致依赖它的 Bean 注入错误类型
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped (e.g. as part of auto-proxy creation). This is often the result of " +
"over-eager type matching - consider using 'getBeanNamesForType' with the " +
"'allowEagerInit' flag turned off, for example.");
}
}
}
}
// ... (省略注册 DisposableBean、销毁方法等)
return exposedObject;
}
二、超详细分步解析 (结合关键源码方法)
1. 实例化 (createBeanInstance())
- 目标:创建一个 Java 对象实例。
- 核心逻辑 (
SimpleInstantiationStrategy.instantiate()/CglibSubclassingInstantiationStrategy.instantiate()):- 解析构造方法 (
ConstructorResolver.autowireConstructor()或ConstructorResolver.instantiateUsingFactoryMethod()或ConstructorResolver.instantiateBean())- 检查
@Autowired标注的构造方法。 - 尝试匹配参数 (
args)。 - 如果无明确指定,使用默认无参构造。
- 检查
- 选择实例化策略:
SimpleInstantiationStrategy:直接反射调用Constructor.newInstance(args)。CglibSubclassingInstantiationStrategy:当 Bean 定义要求方法重写 (如lookup-method,replace-method) 时,使用 CGLIB 动态生成子类并实例化 (Enhancer.create())。否则也使用反射。
- 输出:一个原始对象 (
BeanWrapper包装),属性为默认值 (null, 0, false 等)。
- 解析构造方法 (
2. 应用 MergedBeanDefinitionPostProcessor (applyMergedBeanDefinitionPostProcessors())
- 目标:允许后置处理器在属性填充前修改合并后的
BeanDefinition或缓存元数据。 - 关键处理器:
AutowiredAnnotationBeanPostProcessor:扫描类,查找@Autowired,@Value,@Inject注解的字段和方法,将它们缓存到InjectionMetadata中,供后续依赖注入使用。CommonAnnotationBeanPostProcessor:扫描类,查找@PostConstruct,@PreDestroy,@Resource注解,缓存相关信息。ApplicationListenerDetector:检测实现了ApplicationListener接口的 Bean,为后续事件发布做准备。
- 意义:此步骤是性能优化的关键,避免了在每次属性填充时重复解析注解。
3. 提前暴露早期引用 (addSingletonFactory()) - 解决循环依赖核心
- 条件:单例 (
singleton) + 允许循环依赖 (allowCircularReferences) + 当前 Bean 正在创建中 (isSingletonCurrentlyInCreation返回true)。 - 动作:将一个
ObjectFactory对象放入三级缓存 (singletonFactories)。addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); getEarlyBeanReference()详解:- 遍历所有
SmartInstantiationAwareBeanPostProcessor。 - 调用其
getEarlyBeanReference(bean, beanName)方法。 - 核心处理器:
AbstractAutoProxyCreator(AOP 代理创建器)。- 如果当前 Bean 需要被代理 (匹配切面),则在此处提前生成代理对象 (JDK Proxy 或 CGLIB Proxy)。
- 如果不需要代理,则直接返回原始 Bean (
bean)。
- 输出:一个可能被代理包装的早期引用对象。这个对象会被放入二级缓存 (
earlySingletonObjects) 供其他 Bean 注入使用,同时从三级缓存移除。
- 遍历所有
4. 属性填充/依赖注入 (populateBean())
- 目标:为 Bean 实例设置属性值和解决依赖。
- 详细步骤:
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation():- 在属性填充之前执行。如果任何处理器返回
false,则跳过后续所有属性填充步骤。 - 默认实现返回
true。
- 在属性填充之前执行。如果任何处理器返回
- 依赖解析与自动装配:
- 根据
BeanDefinition的autowireMode决定装配方式 (AUTOWIRE_BY_NAME,AUTOWIRE_BY_TYPE,AUTOWIRE_CONSTRUCTOR已使用过)。 - 对于基于注解的装配 (
@Autowired,@Value),其解析工作已在MergedBeanDefinitionPostProcessor阶段完成,缓存于InjectionMetadata。
- 根据
InstantiationAwareBeanPostProcessor.postProcessProperties():- ★ 依赖注入的核心执行阶段 ★
- 遍历所有
InstantiationAwareBeanPostProcessor。 - 调用
postProcessProperties(PropertyValues pvs, Object bean, String beanName)。 - 核心处理器:
AutowiredAnnotationBeanPostProcessor- 从缓存的
InjectionMetadata中获取需要注入的元素 (字段、方法)。 - 对于每个元素:
- 解析依赖的值 (对于其他 Bean 的依赖,调用
beanFactory.resolveDependency()->beanFactory.getBean(),这可能触发其他 Bean 的创建流程,是循环依赖发生的源头)。 - 使用反射 (
Field.set(),Method.invoke()) 将解析到的值注入到当前 Bean 实例中。
- 解析依赖的值 (对于其他 Bean 的依赖,调用
- 从缓存的
- 核心处理器:
CommonAnnotationBeanPostProcessor- 处理
@Resource注解的注入 (按名称优先)。 - 处理
@PostConstruct/@PreDestroy的缓存 (实际执行在初始化阶段)。
- 处理
- 应用显式定义的属性值:
- 如果通过 XML 或
@Bean的PropertyValues定义了属性值,在这里应用 (applyPropertyValues())。
- 如果通过 XML 或
5. 初始化 (initializeBean())
- 目标:执行初始化回调,应用 BeanPostProcessor,可能生成最终代理对象。
- 详细步骤 (
AbstractAutowireCapableBeanFactory.initializeBean()):- 调用 Aware 接口方法:
- 如果 Bean 实现了
BeanNameAware,调用setBeanName(beanName)。 - 如果 Bean 实现了
BeanClassLoaderAware,调用setBeanClassLoader(ClassLoader)。 - 如果 Bean 实现了
BeanFactoryAware,调用setBeanFactory(BeanFactory)。 - 如果 Bean 实现了
EnvironmentAware,ResourceLoaderAware等,调用相应方法 (这些通常由ApplicationContextAwareProcessor在下一步处理)。
- 如果 Bean 实现了
BeanPostProcessor.postProcessBeforeInitialization():- 遍历所有
BeanPostProcessor。 - 调用
postProcessBeforeInitialization(Object bean, String beanName)。 - 核心处理器:
ApplicationContextAwareProcessor- 处理
EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware接口,注入相应依赖。
- 处理
- 核心处理器:
InitDestroyAnnotationBeanPostProcessor(由CommonAnnotationBeanPostProcessor继承)- 查找并执行
@PostConstruct注解标记的方法。
- 查找并执行
- 遍历所有
- 调用自定义初始化方法:
- 如果 Bean 实现了
InitializingBean接口,调用afterPropertiesSet()方法。 - 调用通过
@Bean(initMethod = "...")或 XML 的init-method属性指定的自定义初始化方法。
- 如果 Bean 实现了
BeanPostProcessor.postProcessAfterInitialization():- ★ 生成 AOP 代理的关键阶段 ★
- 遍历所有
BeanPostProcessor。 - 调用
postProcessAfterInitialization(Object bean, String beanName)。 - 核心处理器:
AnnotationAwareAspectJAutoProxyCreator(继承自AbstractAutoProxyCreator)- 检查当前 Bean 是否匹配任何定义的切面 (
Advisor)。检查缓存或执行匹配逻辑。 - 如果匹配,则创建代理对象:
- 优先尝试 JDK 动态代理 (如果 Bean 实现了接口)。
- 否则使用 CGLIB 生成子类代理。
- 代理对象内部持有目标 Bean (原始对象或早期引用),并织入通知 (
Advice)。 - 返回代理对象。这个代理对象会成为最终放入容器的 Bean (
exposedObject)。 - 如果不匹配,则直接返回原始 Bean (
bean)。
- 检查当前 Bean 是否匹配任何定义的切面 (
- 调用 Aware 接口方法:
6. 处理循环依赖的最终一致性
- 场景:Bean A 依赖 Bean B,Bean B 依赖 Bean A。在创建 A 时,提前暴露了 A 的早期引用 (可能是原始对象或早期代理) 给 B。B 完成创建后,A 继续初始化,期间可能被 AOP 代理 (
postProcessAfterInitialization阶段)。 - 问题:B 中持有的 A 引用是早期引用,而容器最终存储的 A 是代理对象。两者类型不一致!
- 解决方案:在
doCreateBean的最后阶段 (earlySingletonExposure块内):- 从一级缓存 (
singletonObjects) 或二级缓存 (earlySingletonObjects) 获取 Bean A 的引用 (earlySingletonReference)。 - 比较最终暴露的对象 (
exposedObject) 和最初实例化的原始对象 (bean):- 如果
exposedObject == bean:说明初始化没有改变 Bean 的引用 (没有被代理)。那么exposedObject可以直接替换为earlySingletonReference(确保 B 持有的是最终版本)。 - 如果
exposedObject != bean:说明初始化改变了 Bean 的引用 (通常是被代理了)。此时需要检查:- 是否有其他 Bean (如 B) 实际依赖了 A 的原始版本 (
hasDependentBean(beanName)+getDependentBeans(beanName)+removeSingletonIfCreatedForTypeCheckOnly)。 - 如果存在这样的依赖 (
actualDependentBeans非空),则抛出BeanCurrentlyInCreationException。因为 B 期望的是原始 A,但实际拿到的是代理 A,类型不匹配会导致运行时错误。这是 Spring 无法解决构造器注入循环依赖的根本原因,也是allowRawInjectionDespiteWrapping配置项的来源 (强制允许,不推荐)。
- 是否有其他 Bean (如 B) 实际依赖了 A 的原始版本 (
- 如果
- 从一级缓存 (
三、超详细 Mermaid 流程图 (包含三级缓存交互)
四、关键总结
- 流程核心:实例化 -> (MergedBD PostProcessor) -> 提前暴露 (解决循环依赖) -> 属性注入 (触发递归创建) -> Aware 接口 -> BeforeInit -> 自定义Init -> AfterInit (AOP 代理)。
- 循环依赖:通过三级缓存 (
singletonFactories->earlySingletonObjects->singletonObjects) 解决 Setter/Field 注入的循环依赖。构造器注入无法解决,因为实例化前无法暴露引用。 - AOP 代理时机:
- 首选在提前暴露阶段 (
getEarlyBeanReference) 创建,避免最终一致性错误。 - 如果提前暴露时条件不满足 (如切面还未解析),则在
postProcessAfterInitialization阶段创建。
- 首选在提前暴露阶段 (
- 注解处理:
@Autowired/@Value:由AutowiredAnnotationBeanPostProcessor在postProcessProperties阶段处理注入。@PostConstruct:由InitDestroyAnnotationBeanPostProcessor(在CommonAnnotationBeanPostProcessor中) 在postProcessBeforeInitialization阶段触发执行。@Resource:由CommonAnnotationBeanPostProcessor在postProcessProperties阶段处理注入。
- 最终一致性:容器严格确保依赖注入的引用类型一致性。如果因代理导致类型变化且存在依赖原始类型的 Bean,将抛出异常,除非配置
allowRawInjectionDespiteWrapping=true(不推荐)。
本文来自博客园,作者:NeoLshu,转载请注明原文链接:https://www.cnblogs.com/neolshu/p/19120646

浙公网安备 33010602011771号