IoC容器深度解析(三):Bean生命周期11步骤深度剖析,彻底搞懂Spring核心机制!

系列文章第3篇(完结篇)| 共3篇

难度:⭐⭐⭐⭐ | 适合人群:想深入掌握Spring核心原理的开发者


📝 系列回顾

经过前两篇的学习,我们已经掌握了:

  • 第一篇: IoC和DI概念、手写简易IoC容器、BeanFactory基础
  • 第二篇: ApplicationContext深入、七大核心区别、启动流程

上期思考题解答:

Q1: ApplicationContext启动时,所有Bean都会创建吗?
A: 不是!@Lazy标记的Bean、prototype作用域的Bean不会在启动时创建。

Q2: Bean创建失败会怎样?
A: ApplicationContext启动失败(快速失败),BeanFactory运行时才报错。

Q3: Bean生命周期有哪些阶段?
A: 今天详细解答,11个完整步骤!


💥 开场:一次诡异的Bug

时间: 周四晚上8点
地点: 办公室(加班中)
事件: 线上Bug紧急修复

产品经理: "用户反馈订单创建后没收到短信通知!"

我: "让我看看..." 😰


查看代码:

java 复制代码
@Service
public class OrderService {
    
    @Autowired
    private SmsService smsService;
    
    private String notificationPhone;  // 通知手机号
    
    // 从配置文件读取
    @Value("${notification.phone}")
    public void setNotificationPhone(String phone) {
        this.notificationPhone = phone;
        System.out.println("设置通知手机号:" + phone);
    }
    
    public void createOrder(Order order) {
        // 保存订单...
        
        // 发送短信
        smsService.send(notificationPhone, "新订单:" + order.getId());
    }
}

测试:

java 复制代码
@SpringBootTest
public class OrderServiceTest {
    
    @Autowired
    private OrderService orderService;
    
    @Test
    public void testCreateOrder() {
        Order order = new Order(123L);
        orderService.createOrder(order);  // 报错:notificationPhone is null
    }
}

我: "WTF?明明配置了notification.phone=13800138000,为啥是null?" 😱


第二天,请教架构师老李:

老李: "你的@Value注入时机有问题。"

我: "啥意思?" 🤔

老李: "你有没有在构造器里用notificationPhone?"

我: "有啊..."

java 复制代码
public OrderService() {
    System.out.println("构造器:notificationPhone = " + notificationPhone);
    // 输出:构造器:notificationPhone = null
}

老李: "这就是问题!Spring创建Bean的生命周期有11个步骤,@Value注入是在属性填充阶段 ,而构造器执行在实例化阶段,构造器执行时属性还没注入!"

我: "原来如此!那生命周期具体是怎样的?" 💡

老李: "来,我给你画个图..."


🎯 第一问:Bean生命周期概览

完整的11个步骤

kotlin 复制代码
Bean生命周期(11步骤)
│
├─ 1. 实例化(Instantiation)
│    └─ 调用构造器创建Bean实例
│
├─ 2. 属性填充(Populate Properties)
│    └─ @Autowired、@Value注入
│
├─ 3. 设置Bean名称(setBeanName)
│    └─ 如果实现了BeanNameAware
│
├─ 4. 设置BeanFactory(setBeanFactory)
│    └─ 如果实现了BeanFactoryAware
│
├─ 5. 设置ApplicationContext(setApplicationContext)
│    └─ 如果实现了ApplicationContextAware
│
├─ 6. BeanPostProcessor前置处理(postProcessBeforeInitialization)
│    └─ 所有BeanPostProcessor的前置方法
│
├─ 7. 初始化前(@PostConstruct)
│    └─ 执行@PostConstruct标记的方法
│
├─ 8. 初始化(afterPropertiesSet)
│    └─ 如果实现了InitializingBean
│
├─ 9. 自定义初始化方法(init-method)
│    └─ 执行自定义init方法
│
├─ 10. BeanPostProcessor后置处理(postProcessAfterInitialization)
│     └─ 所有BeanPostProcessor的后置方法(AOP代理在这里)
│
└─ 11. 销毁(Destruction)
     ├─ @PreDestroy方法
     ├─ DisposableBean的destroy()
     └─ 自定义destroy-method

生命周期流程图

scss 复制代码
        [容器启动]
            ↓
    ┌───────────────────┐
    │ 1. 实例化Bean     │ ← new Person()
    │   (构造器)        │
    └───────────────────┘
            ↓
    ┌───────────────────┐
    │ 2. 属性填充       │ ← @Autowired、@Value
    │                   │
    └───────────────────┘
            ↓
    ┌───────────────────┐
    │ 3-5. Aware接口    │ ← setBeanName、setBeanFactory等
    │                   │
    └───────────────────┘
            ↓
    ┌───────────────────┐
    │ 6. Before前置处理 │ ← BeanPostProcessor
    │                   │
    └───────────────────┘
            ↓
    ┌───────────────────┐
    │ 7-9. 初始化       │ ← @PostConstruct、init
    │                   │
    └───────────────────┘
            ↓
    ┌───────────────────┐
    │ 10. After后置处理 │ ← BeanPostProcessor(AOP)
    │                   │
    └───────────────────┘
            ↓
    ┌───────────────────┐
    │  Bean就绪,可使用  │
    └───────────────────┘
            ↓
    [容器关闭]
            ↓
    ┌───────────────────┐
    │ 11. 销毁          │ ← @PreDestroy、destroy
    │                   │
    └───────────────────┘

💻 第二问:手写代码验证每个步骤

创建完整的生命周期Bean

java 复制代码
package com.example.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 完整生命周期演示Bean
 */
@Component
public class LifecycleBean implements 
        BeanNameAware,              // 步骤3
        BeanFactoryAware,           // 步骤4
        ApplicationContextAware,    // 步骤5
        InitializingBean,           // 步骤8
        DisposableBean {            // 步骤11
    
    private String name;
    
    // ========== 步骤1:实例化(构造器) ==========
    public LifecycleBean() {
        System.out.println("1. 【实例化】构造器被调用");
    }
    
    // ========== 步骤2:属性填充 ==========
    // @Autowired、@Value在这个阶段注入
    // Spring通过反射设置属性值
    
    public void setName(String name) {
        this.name = name;
        System.out.println("2. 【属性填充】setName: " + name);
    }
    
    // ========== 步骤3:BeanNameAware ==========
    @Override
    public void setBeanName(String name) {
        System.out.println("3. 【BeanNameAware】setBeanName: " + name);
    }
    
    // ========== 步骤4:BeanFactoryAware ==========
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("4. 【BeanFactoryAware】setBeanFactory: " + 
            beanFactory.getClass().getSimpleName());
    }
    
    // ========== 步骤5:ApplicationContextAware ==========
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) 
            throws BeansException {
        System.out.println("5. 【ApplicationContextAware】setApplicationContext: " + 
            applicationContext.getClass().getSimpleName());
    }
    
    // 步骤6:BeanPostProcessor.postProcessBeforeInitialization
    // (在自定义的BeanPostProcessor中实现,见下文)
    
    // ========== 步骤7:@PostConstruct ==========
    @PostConstruct
    public void postConstruct() {
        System.out.println("7. 【@PostConstruct】postConstruct方法被调用");
    }
    
    // ========== 步骤8:InitializingBean ==========
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("8. 【InitializingBean】afterPropertiesSet方法被调用");
    }
    
    // ========== 步骤9:自定义init方法 ==========
    public void customInit() {
        System.out.println("9. 【自定义init】customInit方法被调用");
    }
    
    // 步骤10:BeanPostProcessor.postProcessAfterInitialization
    // (在自定义的BeanPostProcessor中实现,见下文)
    
    // Bean就绪,可以使用了
    
    // ========== 步骤11:销毁阶段 ==========
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("11.1 【@PreDestroy】preDestroy方法被调用");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("11.2 【DisposableBean】destroy方法被调用");
    }
    
    public void customDestroy() {
        System.out.println("11.3 【自定义destroy】customDestroy方法被调用");
    }
}

自定义BeanPostProcessor

java 复制代码
package com.example.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 自定义BeanPostProcessor
 * 用于步骤6和步骤10
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    
    /**
     * 步骤6:初始化前置处理
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
            throws BeansException {
        
        // 只处理我们的LifecycleBean
        if (bean instanceof LifecycleBean) {
            System.out.println("6. 【BeanPostProcessor】postProcessBeforeInitialization: " + 
                beanName);
        }
        
        return bean;  // 必须返回bean
    }
    
    /**
     * 步骤10:初始化后置处理
     * AOP代理就是在这里创建的!
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) 
            throws BeansException {
        
        if (bean instanceof LifecycleBean) {
            System.out.println("10. 【BeanPostProcessor】postProcessAfterInitialization: " + 
                beanName);
            
            // 这里可以返回代理对象
            // return Proxy.newProxyInstance(...);
        }
        
        return bean;
    }
}

配置类

java 复制代码
package com.example.lifecycle;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.example.lifecycle")
public class LifecycleConfig {
    
    @Bean(initMethod = "customInit", destroyMethod = "customDestroy")
    public LifecycleBean lifecycleBean() {
        LifecycleBean bean = new LifecycleBean();
        bean.setName("TestBean");
        return bean;
    }
}

测试类

java 复制代码
package com.example.lifecycle;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class LifecycleTest {
    
    public static void main(String[] args) {
        System.out.println("========== 容器启动 ==========\n");
        
        // 创建容器(Bean会在这里创建)
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(LifecycleConfig.class);
        
        System.out.println("\n========== Bean已就绪 ==========\n");
        
        // 获取Bean
        LifecycleBean bean = context.getBean(LifecycleBean.class);
        System.out.println("获取到Bean: " + bean);
        
        System.out.println("\n========== 关闭容器 ==========\n");
        
        // 关闭容器(触发销毁)
        context.close();
        
        System.out.println("\n========== 容器已关闭 ==========");
    }
}

运行结果

markdown 复制代码
========== 容器启动 ==========

1. 【实例化】构造器被调用
2. 【属性填充】setName: TestBean
3. 【BeanNameAware】setBeanName: lifecycleBean
4. 【BeanFactoryAware】setBeanFactory: DefaultListableBeanFactory
5. 【ApplicationContextAware】setApplicationContext: AnnotationConfigApplicationContext
6. 【BeanPostProcessor】postProcessBeforeInitialization: lifecycleBean
7. 【@PostConstruct】postConstruct方法被调用
8. 【InitializingBean】afterPropertiesSet方法被调用
9. 【自定义init】customInit方法被调用
10. 【BeanPostProcessor】postProcessAfterInitialization: lifecycleBean

========== Bean已就绪 ==========

获取到Bean: com.example.lifecycle.LifecycleBean@1a2b3c4d

========== 关闭容器 ==========

11.1 【@PreDestroy】preDestroy方法被调用
11.2 【DisposableBean】destroy方法被调用
11.3 【自定义destroy】customDestroy方法被调用

========== 容器已关闭 ==========

完美!11个步骤全部验证!


🔍 第三问:源码深度解析

核心方法:doCreateBean()

位置: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

源码(简化版):

java 复制代码
/**
 * 实际创建Bean的方法
 */
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
    
    // ========== 步骤1:实例化Bean ==========
    BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
    Object bean = instanceWrapper.getWrappedInstance();
    
    // 允许提前暴露(解决循环依赖)
    boolean earlySingletonExposure = (mbd.isSingleton() && 
        this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
    
    if (earlySingletonExposure) {
        // 将Bean放入三级缓存
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    
    // ========== 步骤2:属性填充 ==========
    populateBean(beanName, mbd, instanceWrapper);
    
    // ========== 步骤3-10:初始化Bean ==========
    Object exposedObject = initializeBean(beanName, bean, mbd);
    
    // 处理循环依赖
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            exposedObject = earlySingletonReference;
        }
    }
    
    // 注册销毁回调
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
    
    return exposedObject;
}

步骤1:实例化Bean

java 复制代码
/**
 * 创建Bean实例
 */
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, 
        Object[] args) {
    
    Class<?> beanClass = mbd.getBeanClass();
    
    // 1. 使用工厂方法
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    
    // 2. 使用构造器自动装配
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }
    
    // 3. 使用默认构造器
    return instantiateBean(beanName, mbd);
}

/**
 * 使用默认构造器实例化
 */
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
    Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
    BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    initBeanWrapper(bw);
    return bw;
}

关键点:

  • 优先使用工厂方法
  • 其次使用有参构造器(自动装配)
  • 最后使用无参构造器
  • 使用反射创建实例:Constructor.newInstance()

步骤2:属性填充

java 复制代码
/**
 * 填充Bean属性
 */
protected void populateBean(String beanName, RootBeanDefinition mbd, 
        BeanWrapper bw) {
    
    // 1. 执行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = 
                (InstantiationAwareBeanPostProcessor) bp;
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;  // 如果返回false,跳过属性填充
            }
        }
    }
    
    // 2. 获取属性值
    PropertyValues pvs = mbd.getPropertyValues();
    
    // 3. 自动装配(byName或byType)
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
    }
    else if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
    }
    
    // 4. 执行InstantiationAwareBeanPostProcessor的postProcessProperties
    // @Autowired、@Value就是在这里注入的!
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = 
                (InstantiationAwareBeanPostProcessor) bp;
            PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse != null) {
                pvs = pvsToUse;
            }
        }
    }
    
    // 5. 应用属性值
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

关键点:

  • @Autowired通过AutowiredAnnotationBeanPostProcessor处理
  • @Value通过AutowiredAnnotationBeanPostProcessor处理
  • 使用反射设置字段值:Field.set()

步骤3-10:初始化Bean

java 复制代码
/**
 * 初始化Bean
 */
protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
    
    // ========== 步骤3-5:Aware接口回调 ==========
    invokeAwareMethods(beanName, bean);
    
    Object wrappedBean = bean;
    
    // ========== 步骤6:BeanPostProcessor前置处理 ==========
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    
    // ========== 步骤7-9:初始化方法 ==========
    invokeInitMethods(beanName, wrappedBean, mbd);
    
    // ========== 步骤10:BeanPostProcessor后置处理 ==========
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    
    return wrappedBean;
}

步骤3-5:Aware接口回调

java 复制代码
/**
 * 执行Aware接口方法
 */
private void invokeAwareMethods(String beanName, Object bean) {
    
    if (bean instanceof Aware) {
        
        // 步骤3:BeanNameAware
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        
        // 步骤4:BeanClassLoaderAware
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        
        // 步骤4:BeanFactoryAware
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(this);
        }
    }
}

// 步骤5:ApplicationContextAware在ApplicationContextAwareProcessor中处理
// 这是一个BeanPostProcessor

步骤6:前置处理

java 复制代码
/**
 * BeanPostProcessor前置处理
 */
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, 
        String beanName) throws BeansException {
    
    Object result = existingBean;
    
    // 遍历所有BeanPostProcessor
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    
    return result;
}

重要的BeanPostProcessor:

  • ApplicationContextAwareProcessor:处理ApplicationContextAware
  • CommonAnnotationBeanPostProcessor:处理@PostConstruct@PreDestroy
  • InitDestroyAnnotationBeanPostProcessor:处理JSR-250注解

步骤7-9:初始化方法

java 复制代码
/**
 * 执行初始化方法
 */
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)
        throws Throwable {
    
    // 步骤7:@PostConstruct
    // 已经在CommonAnnotationBeanPostProcessor的前置处理中执行了
    
    // 步骤8:InitializingBean
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean) {
        ((InitializingBean) bean).afterPropertiesSet();
    }
    
    // 步骤9:自定义init方法
    if (mbd != null && !isInitializingBean) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

/**
 * 执行自定义init方法
 */
protected void invokeCustomInitMethod(String beanName, Object bean, 
        RootBeanDefinition mbd) throws Throwable {
    
    String initMethodName = mbd.getInitMethodName();
    Method initMethod = mbd.getResolvedInitMethod();
    
    if (initMethod == null) {
        initMethod = beanClass.getMethod(initMethodName);
        mbd.resolvedInitMethod = initMethod;
    }
    
    // 反射调用init方法
    ReflectionUtils.makeAccessible(initMethod);
    initMethod.invoke(bean);
}

步骤10:后置处理(AOP代理)

java 复制代码
/**
 * BeanPostProcessor后置处理
 */
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, 
        String beanName) throws BeansException {
    
    Object result = existingBean;
    
    // 遍历所有BeanPostProcessor
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;  // 可能返回代理对象
    }
    
    return result;
}

重要的BeanPostProcessor:

  • AbstractAutoProxyCreator:AOP代理在这里创建!
  • AsyncAnnotationBeanPostProcessor:处理@Async

AOP代理创建:

java 复制代码
// AbstractAutoProxyCreator的postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        
        // 如果需要代理
        if (shouldProxyTargetClass(beanClass, beanName)) {
            // 创建代理对象
            return createProxy(bean.getClass(), beanName, 
                specificInterceptors, targetSource);
        }
    }
    return bean;
}

步骤11:销毁Bean

java 复制代码
/**
 * 销毁Bean
 */
public void destroyBean(String beanName, Object beanInstance) {
    
    // 步骤11.1:@PreDestroy
    // 由CommonAnnotationBeanPostProcessor处理
    
    // 步骤11.2:DisposableBean
    if (beanInstance instanceof DisposableBean) {
        ((DisposableBean) beanInstance).destroy();
    }
    
    // 步骤11.3:自定义destroy方法
    String destroyMethodName = mbd.getDestroyMethodName();
    if (destroyMethodName != null) {
        invokeCustomDestroyMethod(beanInstance, destroyMethodName);
    }
}

🎯 第四问:循环依赖与三级缓存

什么是循环依赖?

java 复制代码
@Component
public class A {
    @Autowired
    private B b;  // A依赖B
}

@Component
public class B {
    @Autowired
    private A a;  // B依赖A
}

问题:

css 复制代码
创建A → 需要注入B → 创建B → 需要注入A → 创建A → ...

无限循环! 🔄


Spring的解决方案:三级缓存

三级缓存定义:

java 复制代码
public class DefaultSingletonBeanRegistry {
    
    /** 一级缓存:单例对象缓存(成品) */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    /** 二级缓存:早期单例对象缓存(半成品) */
    private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
    
    /** 三级缓存:单例工厂缓存(工厂) */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
}

三级缓存解决流程

场景:A和B循环依赖

css 复制代码
1. 创建A
   ├─ 实例化A(调用构造器)
   ├─ 将A的工厂放入三级缓存
   ├─ 填充A的属性
   │   └─ 需要注入B
   │       ├─ 创建B
   │       │   ├─ 实例化B
   │       │   ├─ 将B的工厂放入三级缓存
   │       │   ├─ 填充B的属性
   │       │   │   └─ 需要注入A
   │       │   │       ├─ 从三级缓存获取A的工厂
   │       │   │       ├─ 调用工厂创建A的早期引用
   │       │   │       ├─ 放入二级缓存
   │       │   │       └─ 返回A的早期引用给B ✅
   │       │   ├─ B的属性填充完成
   │       │   └─ B初始化完成,放入一级缓存
   │       └─ 返回B给A ✅
   ├─ A的属性填充完成
   └─ A初始化完成,放入一级缓存

获取Bean的源码

java 复制代码
/**
 * 获取单例Bean
 */
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    
    // 1. 从一级缓存获取(成品)
    Object singletonObject = this.singletonObjects.get(beanName);
    
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        
        // 2. 从二级缓存获取(半成品)
        singletonObject = this.earlySingletonObjects.get(beanName);
        
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                
                // 双重检查
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    
                    if (singletonObject == null) {
                        // 3. 从三级缓存获取工厂
                        ObjectFactory<?> singletonFactory = 
                            this.singletonFactories.get(beanName);
                        
                        if (singletonFactory != null) {
                            // 调用工厂创建对象
                            singletonObject = singletonFactory.getObject();
                            
                            // 放入二级缓存
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            
                            // 移除三级缓存
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    
    return singletonObject;
}

为什么需要三级缓存?

Q:二级缓存不够吗?

A: 为了支持AOP代理!

场景:

java 复制代码
@Component
public class A {
    @Autowired
    private B b;
}

@Component
public class B {
    @Autowired
    private A a;  // 这里需要的是A的代理对象,不是原始对象
}

解决:

java 复制代码
// 三级缓存中存的是ObjectFactory
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

// getEarlyBeanReference会调用所有SmartInstantiationAwareBeanPostProcessor
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = 
                (SmartInstantiationAwareBeanPostProcessor) bp;
            // 这里可以返回代理对象!
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
        }
    }
    return exposedObject;
}

总结:

  • 一级缓存:存放完全初始化好的Bean
  • 二级缓存:存放实例化但未初始化的Bean(可能是代理对象)
  • 三级缓存:存放Bean工厂,用于创建早期引用(支持AOP)

💻 第五问:实战案例分析

案例1:@PostConstruct vs InitializingBean vs init-method

哪个先执行?

java 复制代码
@Component
public class InitOrderBean implements InitializingBean {
    
    @PostConstruct
    public void postConstruct() {
        System.out.println("1. @PostConstruct");
    }
    
    @Override
    public void afterPropertiesSet() {
        System.out.println("2. InitializingBean.afterPropertiesSet");
    }
    
    public void customInit() {
        System.out.println("3. custom init-method");
    }
}

@Configuration
public class AppConfig {
    @Bean(initMethod = "customInit")
    public InitOrderBean initOrderBean() {
        return new InitOrderBean();
    }
}

输出:

markdown 复制代码
1. @PostConstruct
2. InitializingBean.afterPropertiesSet
3. custom init-method

推荐使用顺序:

  1. 优先: @PostConstruct(JSR-250标准,推荐)
  2. 次选: InitializingBean(Spring特定接口,侵入性)
  3. 最后: init-method(XML配置时代的产物)

案例2:属性注入时机问题(开篇Bug)

错误的写法:

java 复制代码
@Service
public class OrderService {
    
    @Value("${notification.phone}")
    private String notificationPhone;
    
    public OrderService() {
        // ❌ 错误:构造器执行时,@Value还没注入
        System.out.println("构造器:phone = " + notificationPhone);  // null
    }
}

正确的写法1:使用@PostConstruct

java 复制代码
@Service
public class OrderService {
    
    @Value("${notification.phone}")
    private String notificationPhone;
    
    @PostConstruct
    public void init() {
        // ✅ 正确:@PostConstruct在属性注入之后
        System.out.println("PostConstruct:phone = " + notificationPhone);  // 有值
    }
}

正确的写法2:使用构造器注入

java 复制代码
@Service
public class OrderService {
    
    private final String notificationPhone;
    
    // ✅ 正确:构造器注入在实例化时就完成
    @Autowired
    public OrderService(@Value("${notification.phone}") String phone) {
        this.notificationPhone = phone;
        System.out.println("构造器:phone = " + notificationPhone);  // 有值
    }
}

案例3:BeanPostProcessor修改Bean

自定义BeanPostProcessor修改Bean属性:

java 复制代码
@Component
public class UserEnhancePostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        
        if (bean instanceof UserService) {
            UserService userService = (UserService) bean;
            
            // 修改Bean的属性
            userService.setMaxRetry(5);
            System.out.println("增强UserService:设置最大重试次数为5");
        }
        
        return bean;
    }
}

案例4:动态代理Bean

创建代理Bean:

java 复制代码
@Component
public class LogProxyPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        
        // 只为Service层创建代理
        if (bean.getClass().isAnnotationPresent(Service.class)) {
            
            return Proxy.newProxyInstance(
                bean.getClass().getClassLoader(),
                bean.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println(">>> 调用方法:" + method.getName());
                    
                    long start = System.currentTimeMillis();
                    Object result = method.invoke(bean, args);
                    long end = System.currentTimeMillis();
                    
                    System.out.println("<<< 方法执行耗时:" + (end - start) + "ms");
                    return result;
                }
            );
        }
        
        return bean;
    }
}

效果:

java 复制代码
@Service
public class UserService {
    public User getUser(Long id) {
        return new User(id, "张三");
    }
}

// 使用
userService.getUser(1L);

// 输出:
// >>> 调用方法:getUser
// <<< 方法执行耗时:5ms

📊 生命周期完整总结

11步骤速记表

步骤 名称 说明 关键接口/注解 可选/必需
1 实例化 调用构造器 Constructor 必需
2 属性填充 注入依赖 @Autowired、@Value 可选
3 BeanNameAware 设置Bean名称 BeanNameAware 可选
4 BeanFactoryAware 设置BeanFactory BeanFactoryAware 可选
5 ApplicationContextAware 设置ApplicationContext ApplicationContextAware 可选
6 Before前置处理 初始化前处理 BeanPostProcessor 可选
7 @PostConstruct JSR-250初始化 @PostConstruct 可选
8 InitializingBean Spring初始化 InitializingBean 可选
9 init-method 自定义初始化 @Bean(initMethod) 可选
10 After后置处理 初始化后处理(AOP) BeanPostProcessor 可选
11 销毁 Bean销毁 @PreDestroy等 可选

记忆口诀

复制代码
实例化,属性填,
Aware接口三个传。
前置处理拦一道,
三种初始化按顺序来。
后置处理做代理,
Bean就绪可以用。
容器关闭销毁调,
生命周期走一遭。

💡 最佳实践建议

1. 初始化方法选择

推荐顺序:

java 复制代码
// 第一选择:@PostConstruct(推荐)
@PostConstruct
public void init() {
    // JSR-250标准,Spring、JavaEE通用
}

// 第二选择:InitializingBean
@Override
public void afterPropertiesSet() {
    // Spring特定,侵入性强
}

// 第三选择:init-method
@Bean(initMethod = "customInit")
// XML时代产物,不推荐

2. 依赖注入方式选择

推荐:构造器注入

java 复制代码
@Service
public class UserService {
    
    private final UserDao userDao;  // final保证不可变
    
    // 构造器注入(推荐)
    @Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
}

优点:

  • ✅ 依赖明确
  • ✅ 支持final
  • ✅ 便于单元测试
  • ✅ 避免循环依赖

3. 避免在构造器中使用注入的依赖

java 复制代码
// ❌ 错误
@Service
public class OrderService {
    
    @Autowired
    private UserService userService;
    
    public OrderService() {
        userService.getUser(1L);  // NullPointerException
    }
}

// ✅ 正确
@Service
public class OrderService {
    
    @Autowired
    private UserService userService;
    
    @PostConstruct
    public void init() {
        userService.getUser(1L);  // 正常工作
    }
}

4. 自定义BeanPostProcessor注意事项

java 复制代码
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        
        // ⚠️ 注意:不要在这里创建新对象并返回
        // 除非你明确知道自己在做什么(如创建代理)
        
        // ✅ 修改bean属性
        if (bean instanceof UserService) {
            ((UserService) bean).setMaxRetry(5);
        }
        
        // ✅ 必须返回bean
        return bean;
    }
}

5. 循环依赖处理

能解决的情况:

java 复制代码
// ✅ 可以:字段注入 + 单例
@Component
public class A {
    @Autowired
    private B b;
}

@Component
public class B {
    @Autowired
    private A a;
}

无法解决的情况:

java 复制代码
// ❌ 不行:构造器注入 + 循环依赖
@Component
public class A {
    @Autowired
    public A(B b) { }  // 报错
}

@Component
public class B {
    @Autowired
    public B(A a) { }  // 报错
}

// ❌ 不行:原型模式 + 循环依赖
@Component
@Scope("prototype")
public class A {
    @Autowired
    private B b;  // 报错
}

解决方案: 重新设计类的依赖关系,避免循环依赖


🎉 系列总结

三篇文章回顾

第一篇:IoC基础

  • ✅ 理解了IoC和DI概念
  • ✅ 手写了100行简易IoC容器
  • ✅ 学习了BeanFactory接口

第二篇:ApplicationContext

  • ✅ 掌握了ApplicationContext的7大优势
  • ✅ 理解了容器启动流程
  • ✅ 学会了如何选择容器

第三篇:Bean生命周期

  • ✅ 完整掌握11个生命周期步骤
  • ✅ 深入源码级别理解
  • ✅ 理解了三级缓存解决循环依赖

学习路线建议

yaml 复制代码
Level 1: 基础使用 ⭐
└─ 会用@Component、@Autowired

Level 2: 理解原理 ⭐⭐
└─ 理解IoC、DI概念

Level 3: 掌握容器 ⭐⭐⭐
└─ 理解BeanFactory和ApplicationContext

Level 4: 深入生命周期 ⭐⭐⭐⭐
└─ 掌握Bean的11个生命周期步骤

Level 5: 源码级理解 ⭐⭐⭐⭐⭐
└─ 阅读Spring源码,理解实现细节

恭喜你,完成这个系列,你已经达到Level 4! 🎉


下一步学习

推荐深入主题:

  1. AOP原理: 代理模式、切面编程
  2. 事务管理: @Transactional原理
  3. SpringMVC: DispatcherServlet工作流程
  4. SpringBoot自动配置: @EnableAutoConfiguration原理
  5. Spring源码阅读: 从ApplicationContext入手

💬 写在最后

从第一篇到现在,我们一起:

  • 🔧 手写了简易IoC容器
  • 📚 理解了容器的演进
  • 🔬 深入了Bean的生命周期

这个系列到这里就完结了!

如果这个系列对你有帮助,请:

  • 👍 点赞支持
  • ⭐ 收藏备用
  • 🔄 转发分享
  • 💬 评论交流

感谢一路陪伴,期待下个系列再见! 👋

相关推荐
重生之我在二本学院拿offer当牌打3 小时前
秒杀场景下的MySQL优化:从崩溃到抗住100万QPS
后端
重生之我在二本学院拿offer当牌打3 小时前
手写SpringBoot Starter(三):实现可插拔Starter,像Zuul一样优雅!
后端
初见0013 小时前
🌱 SpringBoot自动配置:别装了,我知道你的秘密!🤫
spring boot·后端
用户785127814703 小时前
Python代码获取京东商品详情原数据 API 接口(item_get_app)
后端
JAVA数据结构3 小时前
BPMN-Activiti-简单流程委托
后端
sivdead3 小时前
智能体记忆机制详解
人工智能·后端·agent
拉不动的猪4 小时前
图文引用打包时的常见情景解析
前端·javascript·后端
该用户已不存在4 小时前
程序员的噩梦,祖传代码该怎么下手?
前端·后端
间彧4 小时前
Redis缓存穿透、缓存雪崩、缓存击穿详解与代码实现
后端