文章中如果有图看不到,可以点这里去 csdn 看看。从那边导过来的,文章太多,没法一篇篇修改好。

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 实例设置属性值和解决依赖。
  • 详细步骤
    1. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
      • 在属性填充之前执行。如果任何处理器返回 false,则跳过后续所有属性填充步骤。
      • 默认实现返回 true
    2. 依赖解析与自动装配
      • 根据 BeanDefinitionautowireMode 决定装配方式 (AUTOWIRE_BY_NAME, AUTOWIRE_BY_TYPE, AUTOWIRE_CONSTRUCTOR 已使用过)。
      • 对于基于注解的装配 (@Autowired, @Value),其解析工作已在 MergedBeanDefinitionPostProcessor 阶段完成,缓存于 InjectionMetadata
    3. InstantiationAwareBeanPostProcessor.postProcessProperties()
      • ★ 依赖注入的核心执行阶段 ★
      • 遍历所有 InstantiationAwareBeanPostProcessor
      • 调用 postProcessProperties(PropertyValues pvs, Object bean, String beanName)
      • 核心处理器AutowiredAnnotationBeanPostProcessor
        • 从缓存的 InjectionMetadata 中获取需要注入的元素 (字段、方法)。
        • 对于每个元素:
          • 解析依赖的值 (对于其他 Bean 的依赖,调用 beanFactory.resolveDependency() -> beanFactory.getBean(),这可能触发其他 Bean 的创建流程,是循环依赖发生的源头)。
          • 使用反射 (Field.set(), Method.invoke()) 将解析到的值注入到当前 Bean 实例中。
      • 核心处理器CommonAnnotationBeanPostProcessor
        • 处理 @Resource 注解的注入 (按名称优先)。
        • 处理 @PostConstruct / @PreDestroy 的缓存 (实际执行在初始化阶段)。
    4. 应用显式定义的属性值
      • 如果通过 XML 或 @BeanPropertyValues 定义了属性值,在这里应用 (applyPropertyValues())。

5. 初始化 (initializeBean())

  • 目标:执行初始化回调,应用 BeanPostProcessor,可能生成最终代理对象。
  • 详细步骤 (AbstractAutowireCapableBeanFactory.initializeBean())
    1. 调用 Aware 接口方法
      • 如果 Bean 实现了 BeanNameAware,调用 setBeanName(beanName)
      • 如果 Bean 实现了 BeanClassLoaderAware,调用 setBeanClassLoader(ClassLoader)
      • 如果 Bean 实现了 BeanFactoryAware,调用 setBeanFactory(BeanFactory)
      • 如果 Bean 实现了 EnvironmentAware, ResourceLoaderAware 等,调用相应方法 (这些通常由 ApplicationContextAwareProcessor 在下一步处理)。
    2. BeanPostProcessor.postProcessBeforeInitialization()
      • 遍历所有 BeanPostProcessor
      • 调用 postProcessBeforeInitialization(Object bean, String beanName)
      • 核心处理器ApplicationContextAwareProcessor
        • 处理 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware 接口,注入相应依赖。
      • 核心处理器InitDestroyAnnotationBeanPostProcessor (由 CommonAnnotationBeanPostProcessor 继承)
        • 查找并执行 @PostConstruct 注解标记的方法。
    3. 调用自定义初始化方法
      • 如果 Bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法。
      • 调用通过 @Bean(initMethod = "...") 或 XML 的 init-method 属性指定的自定义初始化方法。
    4. BeanPostProcessor.postProcessAfterInitialization()
      • ★ 生成 AOP 代理的关键阶段 ★
      • 遍历所有 BeanPostProcessor
      • 调用 postProcessAfterInitialization(Object bean, String beanName)
      • 核心处理器AnnotationAwareAspectJAutoProxyCreator (继承自 AbstractAutoProxyCreator)
        • 检查当前 Bean 是否匹配任何定义的切面 (Advisor)。检查缓存或执行匹配逻辑。
        • 如果匹配,则创建代理对象
          • 优先尝试 JDK 动态代理 (如果 Bean 实现了接口)。
          • 否则使用 CGLIB 生成子类代理。
        • 代理对象内部持有目标 Bean (原始对象或早期引用),并织入通知 (Advice)。
        • 返回代理对象。这个代理对象会成为最终放入容器的 Bean (exposedObject)。
        • 如果不匹配,则直接返回原始 Bean (bean)。

6. 处理循环依赖的最终一致性

  • 场景:Bean A 依赖 Bean B,Bean B 依赖 Bean A。在创建 A 时,提前暴露了 A 的早期引用 (可能是原始对象或早期代理) 给 B。B 完成创建后,A 继续初始化,期间可能被 AOP 代理 (postProcessAfterInitialization 阶段)。
  • 问题:B 中持有的 A 引用是早期引用,而容器最终存储的 A 是代理对象。两者类型不一致!
  • 解决方案:在 doCreateBean 的最后阶段 (earlySingletonExposure 块内):
    1. 一级缓存 (singletonObjects)二级缓存 (earlySingletonObjects) 获取 Bean A 的引用 (earlySingletonReference)。
    2. 比较最终暴露的对象 (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 配置项的来源 (强制允许,不推荐)。

三、超详细 Mermaid 流程图 (包含三级缓存交互)

ContainerAbstractAutowireCapableBeanFactoryDefaultSingletonBeanRegistry (三级缓存)BeanPostProcessorsTarget BeanDependent Bean (e.g., B depends on A)doCreateBean(beanName=A, mbd, args)1. INSTANTIATIONcreateBeanInstance() → Raw Bean A createdRaw Bean A★ MergedBeanDefinitionPostProcessorMergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()e.g., AutowiredAnnotationBPP caches @Autowired metadata★ Early Exposure (Solve Circular Dep)addSingletonFactory(A, ObjectFactory)ObjectFactory stored in singletonFactories (Level 3 Cache)alt[isSingleton & allowCircular & inCreation]2. POPULATION (DI)InstantiationAwareBPP.postProcessAfterInstantiation()InstantiationAwareBPP.postProcessProperties()AutowiredAnnotationBPP processes @AutowiredresolveDependency() → Need Bean BgetBean(B) [Recursive Call!]loop[For each dependency field in A]★ Recursive getBean(B) triggers B's creationdoCreateBean(beanName=B, ...)createBeanInstance() → Raw Bean BpopulateBean(B) → Needs A!resolveDependency() → Need Bean A (which is creating)getSingleton(A, allowEarlyRef=true)Check singletonObjects (L1) → Not FoundCheck earlySingletonObjects (L2) → Not Found (First time)Check singletonFactories (L3) → Found ObjectFactory for AObjectFactory.getObject() → getEarlyBeanReference(A)SmartInstantiationAwareBPP.getEarlyBeanReference(A, raw A)Create Proxy for A (wrapping raw A)Proxy A (Early Reference)raw A (Early Reference)alt[A needs AOP?]Move Proxy/raw A from L3 → L2 (earlySingletonObjects)Return Proxy/raw A (Early Reference for A)Inject Early Reference for A into BContinue initializing B (initializeBean(B))BPP.postProcessAfterInitialization(B) → B might be proxiedaddSingleton(B) → B to L1, remove from L2/L3Return fully initialized BB creation completeContinue populateBean(A) with resolved BProperties set on raw A3. INITIALIZATIONInvoke Aware methods (BeanNameAware, etc.)BPP.postProcessBeforeInitialization(A)e.g., @PostConstruct executed by CommonAnnotationBPPInvoke init methods (afterPropertiesSet, custom init)BPP.postProcessAfterInitialization(A)Create Proxy for A (wrapping raw A)Proxy AexposedObject = Proxy AexposedObject = raw Aalt[A needs AOP (if not done early)?]★ Handle Early Ref ConsistencygetSingleton(A, false) → Gets from L1/L2 (Proxy/raw A from L2)Check if exposedObject (Proxy A) == raw A (from start)exposedObject = earlySingletonRef (Proxy/raw A from L2)Check dependent beans needing raw AThrow BeanCurrentlyInCreationExceptionalt[dependent beans exist &!allowRawInjectionDespiteWrapping]alt[exposedObject == raw A (No proxy createdin init)]alt[earlySingletonExposure was true]addSingleton(A) → exposedObject to L1, remove from L2/L3Return fully initialized A (exposedObject)ContainerAbstractAutowireCapableBeanFactoryDefaultSingletonBeanRegistry (三级缓存)BeanPostProcessorsTarget BeanDependent Bean (e.g., B depends on A)

四、关键总结

  1. 流程核心:实例化 -> (MergedBD PostProcessor) -> 提前暴露 (解决循环依赖) -> 属性注入 (触发递归创建) -> Aware 接口 -> BeforeInit -> 自定义Init -> AfterInit (AOP 代理)。
  2. 循环依赖:通过三级缓存 (singletonFactories -> earlySingletonObjects -> singletonObjects) 解决 Setter/Field 注入的循环依赖。构造器注入无法解决,因为实例化前无法暴露引用。
  3. AOP 代理时机
    • 首选在提前暴露阶段 (getEarlyBeanReference) 创建,避免最终一致性错误。
    • 如果提前暴露时条件不满足 (如切面还未解析),则在 postProcessAfterInitialization 阶段创建。
  4. 注解处理
    • @Autowired/@Value:由 AutowiredAnnotationBeanPostProcessorpostProcessProperties 阶段处理注入。
    • @PostConstruct:由 InitDestroyAnnotationBeanPostProcessor (在 CommonAnnotationBeanPostProcessor 中) 在 postProcessBeforeInitialization 阶段触发执行。
    • @Resource:由 CommonAnnotationBeanPostProcessorpostProcessProperties 阶段处理注入。
  5. 最终一致性:容器严格确保依赖注入的引用类型一致性。如果因代理导致类型变化且存在依赖原始类型的 Bean,将抛出异常,除非配置 allowRawInjectionDespiteWrapping=true (不推荐)。
posted @ 2025-09-09 17:10  NeoLshu  阅读(6)  评论(0)    收藏  举报  来源