悦书阁 悦书阁
首页
学习笔记
技术文档
idea插件开发
更多
  • 分类
  • 标签
  • 归档

Felix

大道至简 知易行难
首页
学习笔记
技术文档
idea插件开发
更多
  • 分类
  • 标签
  • 归档
  • JVM

  • spring

    • Spring Bean 生命周期:从源码到实战
      • 先有一张地图
      • 第一阶段:Bean 的生成(13步)
        • 步骤1:扫描并生成 BeanDefinition
        • 步骤2:合并 BeanDefinition(父子继承)
        • 步骤3:加载类
        • 🔧 扩展点1:实例化前干预
        • 步骤4:实例化(创建对象)
        • 🔧 扩展点2:BeanDefinition 后置处理
        • 🔧 扩展点3:实例化后处理
        • 步骤5-6:自动注入与属性处理
        • 🔧 扩展点4:Aware 接口回调
        • 🔧 扩展点5:初始化前处理
        • 步骤7:初始化
        • 🔧 扩展点6:初始化后处理(AOP 在此!)
      • 第二阶段:Bean 的销毁
      • 全流程总览图
      • 常见面试题速查
        • Q1:@Autowired 和 @Resource 的区别?
        • Q2:循环依赖是怎么解决的?
        • Q3:为什么 @Transactional 在 @PostConstruct 中不生效?
      • 总结
    • Spring Aop
    • Spring循环依赖
    • Spring常见问题
  • 并发编程

  • 消息中间件

  • 微服务

  • 三高架构

  • 学习笔记
  • spring
liufei379
2022-06-21
目录

Spring Bean 生命周期:从源码到实战

本文用「人话」讲解 Spring Bean 从创建到销毁的全过程,附带源码级扩展点解析。


# 先有一张地图

Spring Bean 的生命周期可粗分为三大阶段:

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   实例化    │ → │   属性填充   │ → │   初始化    │
│ Instantiation│    │  Populate   │    │ Initialize │
└─────────────┘    └─────────────┘    └─────────────┘
       ↓                                    ↓
  创建对象(new)                      投入使用
1
2
3
4
5
6

细分则包含 13个关键步骤,其中穿插 6个核心扩展点。读完本文,你将能回答:

  • @Autowired 是在哪个阶段注入的?
  • @PostConstruct 和 InitializingBean 哪个先执行?
  • AOP 代理是在什么时候创建的?

# 第一阶段:Bean 的生成(13步)

# 步骤1:扫描并生成 BeanDefinition

Spring 启动时,会扫描 @ComponentScan 指定包下的所有 .class 文件。

关键技术点:

  • 使用 ASM 技术解析字节码(不加载类到 JVM,速度快)
  • 将类信息包装为 BeanDefinition 对象(Bean 的「设计图纸」)
// BeanDefinition 核心属性
public interface BeanDefinition extends AttributeAccessor {
    String getBeanClassName();      // 类名(注意:是字符串,不是 Class 对象)
    String getScope();              // singleton / prototype
    boolean isLazyInit();           // 是否懒加载
    String getInitMethodName();     // 初始化方法
    String getDestroyMethodName();  // 销毁方法
}
1
2
3
4
5
6
7
8

# 步骤2:合并 BeanDefinition(父子继承)

Spring 支持 XML 形式的父子 Bean 定义:

<bean id="parent" class="com.example.Parent" scope="prototype"/>
<bean id="child" class="com.example.Child" parent="parent"/>
1
2

child 会继承 parent 的属性(如 scope)。合并后生成新的 RootBeanDefinition。

💡 实际开发中:注解方式很少用父子 Bean,但 Spring 内部(如配置类处理)会用到此机制。


# 步骤3:加载类

将 BeanDefinition 中的类名字符串,通过类加载器转为 Class<?> 对象。

// AbstractBeanFactory.doGetBean() 中的类加载逻辑
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
1
2

# 🔧 扩展点1:实例化前干预

接口:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()

作用:在对象创建前,给你一个「偷梁换柱」的机会。

@Component
public class MyProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        if ("userService".equals(beanName)) {
            // 直接返回自定义对象,Spring 就不会实例化了!
            return new UserService("直接new的对象");
        }
        return null; // 返回 null,Spring 继续正常流程
    }
}
1
2
3
4
5
6
7
8
9
10
11

⚠️ 注意:若此处返回非空对象,会跳过依赖注入和大部分后续步骤,直接进入「初始化后」步骤。


# 步骤4:实例化(创建对象)

Spring 创建 Bean 对象的三种方式:

方式 示例 优先级
Supplier beanDefinition.setInstanceSupplier(() -> new UserService()) 最高
工厂方法 @Bean 或 factory-method 次之
构造方法 new UserService() 默认

构造方法推断逻辑:

  1. 只有默认无参构造 → 用它
  2. 只有一个有参构造 → 用它
  3. 多个构造方法 → 报错(除非用 @Autowired 指定)
@Component
public class UserService {
    // 这个会被自动选为构造方法
    public UserService(OrderService orderService) {
        this.orderService = orderService;
    }
}
1
2
3
4
5
6
7

# 🔧 扩展点2:BeanDefinition 后置处理

接口:MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()

作用:实例化后、属性赋值前,修改 BeanDefinition。

@Component
public class MyMergedProcessor implements MergedBeanDefinitionPostProcessor {
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, 
                                                Class<?> beanType, String beanName) {
        if ("userService".equals(beanName)) {
            // 手动添加一个属性值(相当于 XML 的 <property>)
            beanDefinition.getPropertyValues().add("orderService", new OrderService());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11

# 🔧 扩展点3:实例化后处理

接口:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()

作用:对象已创建,但还未填充属性。可在这里提前做些初始化。

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
    if ("userService".equals(beanName)) {
        UserService userService = (UserService) bean;
        userService.preInit(); // 自定义预初始化
    }
    return true; // 返回 true 继续流程,false 则跳过属性填充
}
1
2
3
4
5
6
7
8

# 步骤5-6:自动注入与属性处理

Spring 在此阶段处理:

  • @Autowired / @Value(Spring 原生)
  • @Resource(JSR-250 标准)

底层实现:通过 InstantiationAwareBeanPostProcessor.postProcessProperties() 扩展点完成。

// AutowiredAnnotationBeanPostProcessor 的核心逻辑
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 1. 找出所有带 @Autowired 的字段/方法
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    // 2. 注入值
    metadata.inject(bean, beanName, pvs);
    return pvs;
}
1
2
3
4
5
6
7
8

# 🔧 扩展点4:Aware 接口回调

属性填充完成后,Spring 会向 Bean 「汇报」一些上下文信息:

Aware 接口 注入内容
BeanNameAware Bean 的名称
BeanClassLoaderAware 类加载器
BeanFactoryAware BeanFactory 容器
@Component
public class UserService implements BeanNameAware, ApplicationContextAware {
    private String beanName;
    private ApplicationContext context;
    
    @Override
    public void setBeanName(String name) {
        this.beanName = name; // 回调注入
    }
    
    @Override
    public void setApplicationContext(ApplicationContext ctx) {
        this.context = ctx; // 回调注入
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

💡 ApplicationContextAware 是在「初始化前」阶段通过 ApplicationContextAwareProcessor 注入的。


# 🔧 扩展点5:初始化前处理

接口:BeanPostProcessor.postProcessBeforeInitialization()

核心作用:

  1. 执行 @PostConstruct 注解的方法(通过 InitDestroyAnnotationBeanPostProcessor)
  2. 执行更多 Aware 回调(Environment、ResourceLoader 等)
@Component
public class UserService {
    @PostConstruct
    public void init() {
        // 依赖注入完成后执行
        System.out.println("初始化中...");
    }
}
1
2
3
4
5
6
7
8

# 步骤7:初始化

Spring 提供两种初始化方式(按顺序执行):

  1. InitializingBean.afterPropertiesSet()
  2. 自定义 init-method(如 @Bean(initMethod = "init"))
@Component
public class UserService implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        // 校验必填属性、开启资源等
        System.out.println("属性已设置完成,执行初始化逻辑");
    }
}
1
2
3
4
5
6
7
8

📌 执行顺序:@PostConstruct → InitializingBean → init-method


# 🔧 扩展点6:初始化后处理(AOP 在此!)

接口:BeanPostProcessor.postProcessAfterInitialization()

这是最重要的扩展点,Spring AOP 就是在这里生成代理对象的!

// AbstractAutoProxyCreator 的核心逻辑
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        // 检查是否需要代理(是否有 @Transactional、@Aspect 等)
        return wrapIfNecessary(bean, beanName, cacheKey);
    }
    return bean;
}
1
2
3
4
5
6
7
8
9

🎯 关键结论:

  • @Transactional 的代理是在 Bean 初始化完成后 才生成的
  • 因此在 @PostConstruct 中调用同类事务方法,事务不生效(因为那时还是原始对象)

# 第二阶段:Bean 的销毁

当 Spring 容器关闭(如应用停止)时,会触发销毁流程:

// 销毁顺序(与初始化相反)
1. @PreDestroy 注解方法
2. DisposableBean.destroy()
3. 自定义 destroy-method
1
2
3
4
@Component
public class UserService implements DisposableBean {
    @PreDestroy
    public void preDestroy() {
        System.out.println("@PreDestroy 执行");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean 执行");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 全流程总览图

Spring Bean 生命周期完整流程
═══════════════════════════════════════════════════════════════

【生成阶段】
  1. 扫描类 → 生成 BeanDefinition(ASM 解析字节码)
  2. 合并父子 BeanDefinition
  3. 类加载(字符串 → Class<?>)
  ↓
  🔧 扩展点:postProcessBeforeInstantiation() 【可替换对象】
  ↓
  4. 实例化(new / 工厂方法 / Supplier)
  ↓
  🔧 扩展点:postProcessMergedBeanDefinition() 【修改定义】
  🔧 扩展点:postProcessAfterInstantiation() 【实例后处理】
  ↓
  5. 自动注入(@Autowired / @Resource)
  6. 属性填充
  ↓
  🔧 扩展点:Aware 接口回调 【注入上下文】
  ↓
  🔧 扩展点:postProcessBeforeInitialization() 【@PostConstruct 在此】
  ↓
  7. 初始化(InitializingBean / init-method)
  ↓
  🔧 扩展点:postProcessAfterInitialization() 【AOP 代理在此生成!】
  ↓
  ✅ Bean 就绪,投入使用

【销毁阶段】
  1. @PreDestroy
  2. DisposableBean.destroy()
  3. destroy-method
═══════════════════════════════════════════════════════════════
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 常见面试题速查

# Q1:@Autowired 和 @Resource 的区别?

特性 @Autowired @Resource
来源 Spring 原生 JSR-250 标准
默认匹配 先按类型,再按名称 先按名称,再按类型
指定方式 @Qualifier name 属性
处理类 AutowiredAnnotationBeanPostProcessor CommonAnnotationBeanPostProcessor

# Q2:循环依赖是怎么解决的?

Spring 通过 三级缓存 解决 setter 注入的循环依赖:

  • singletonObjects:成品 Bean(完全初始化)
  • earlySingletonObjects:半成品 Bean(已实例化,未填充属性)
  • singletonFactories:Bean 工厂(用于生成代理对象)

⚠️ 构造方法注入的循环依赖无法解决(因为实例化阶段就需要依赖)

# Q3:为什么 @Transactional 在 @PostConstruct 中不生效?

因为事务代理是在 postProcessAfterInitialization() 中生成的,而 @PostConstruct 在 postProcessBeforeInitialization() 中执行,此时还是原始对象,不是代理对象。


# 总结

理解 Spring 生命周期的关键是:知道扩展点在哪里,能解决什么问题。

你的需求 使用的扩展点
自定义依赖注入逻辑 InstantiationAwareBeanPostProcessor.postProcessProperties()
初始化前做点什么 @PostConstruct 或 postProcessBeforeInitialization()
生成 AOP 代理 postProcessAfterInitialization()
修改 BeanDefinition MergedBeanDefinitionPostProcessor

建议通读 AbstractAutowireCapableBeanFactory.doCreateBean() 源码,这是 Bean 生命周期的「主函数」。


本文基于 Spring 5.3.x 源码整理,如有错漏,欢迎指正。

#生命周期#源码
上次更新: 2026/3/11 22:17:56
JVM调优工具以及调优实战
Spring Aop

← JVM调优工具以及调优实战 Spring Aop→

最近更新
01
实现idea开发的关键步骤
10-05
02
Redis高可用架构
09-09
03
Zookeeper高可用
08-31
更多文章>
Theme by Vdoing | Copyright © 2022-2026 Felix | 粤ICP备17101757号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式