Spring Bean 生命周期

xiaopeng
发布于 2026-08-17 / 5 阅读
0
0

Spring Bean 生命周期

Spring Bean 生命周期 ⭐⭐⭐⭐⭐

面试频率:★★★★★
工作频率:★★★★☆


⚡30 秒速记(复习只看这里)

🟢 一句话

Spring Bean 生命周期就是一个 Bean 从创建、依赖注入、初始化、使用到最终销毁的整个过程。

核心流程:

实例化
  ↓
属性填充 / 依赖注入
  ↓
Aware 回调
  ↓
BeanPostProcessor 前置处理
  ↓
初始化
  ↓
BeanPostProcessor 后置处理
  ↓
Bean 创建完成
  ↓
正常使用
  ↓
销毁

🟡 最重要的区别

实例化 ≠ 初始化

实例化:

new UserService();

只是:

把对象创建出来。

初始化:

属性注入完成之后,执行 Bean 的初始化逻辑。


🔴 和循环依赖的关系

Spring 能解决部分循环依赖的关键:

实例化

和

属性填充

不是同一个步骤。

所以可以:

new A()
  ↓
A对象已经存在
  ↓
提前暴露A
  ↓
再给A注入B

📚 一、什么是 Bean 生命周期?

例如:

@Service
public class UserService {

}

Spring 不只是简单执行:

new UserService();

而是经历一整套流程:

创建对象

↓

注入依赖

↓

初始化

↓

Spring管理

↓

正常使用

↓

销毁

这整个过程:

叫做:

Bean 生命周期。


二、第一步:实例化 Bean ⭐⭐⭐⭐⭐

例如:

@Service
public class UserService {

}

Spring 会先:

UserService userService =
        new UserService();

这一步叫:

实例化(Instantiation)


此时:

对象:

已经存在

但是:

Bean 还没有完全创建完成。

例如:

@Service
public class UserService {

    @Autowired
    private OrderService orderService;

}

刚刚:

new UserService();

之后:

userService已经存在

但是:

orderService = null

因为:

依赖注入还没有开始。


所以:

对象实例化

≠

Bean创建完成

三、第二步:属性填充 / 依赖注入 ⭐⭐⭐⭐⭐

实例化完成之后:

Spring 开始给 Bean 注入依赖。

例如:

@Autowired
private OrderService orderService;

Spring:

查找OrderService

↓

获取OrderService Bean

↓

注入UserService

最后:

UserService
     |
     ↓
OrderService

这一步:

叫做:

属性填充(Populate Properties)

也就是我们经常说的:

依赖注入 DI。


四、为什么实例化之后属性还是 null?

因为:

Spring 创建 Bean 是分阶段的。

先:

new UserService();

得到:

UserService对象

这个时候:

orderService = null

然后才:

属性填充

最终:

orderService = OrderService对象

所以:

实例化

↓

属性还是null

↓

依赖注入

↓

属性有值

五、这和循环依赖有什么关系? ⭐⭐⭐⭐⭐

假设:

A依赖B

B依赖A

字段注入:

class A {

    @Autowired
    private B b;

}

B:

class B {

    @Autowired
    private A a;

}

Spring 可以:

new A()

此时:

A已经存在

但是:

A.b = null

Spring 可以:

提前暴露A

然后:

创建B

B需要A:

拿到提前暴露的A

B创建完成。

再:

把B注入A

最终:

A → B

B → A

所以:

Spring 能解决部分循环依赖的重要原因就是:

实例化和属性填充是两个不同阶段。


六、第三步:Aware 回调

Spring 提供了一些:

Aware接口

例如:

BeanNameAware

BeanFactoryAware

ApplicationContextAware

作用:

让 Bean 感知 Spring 容器中的一些信息。


例如:

public class UserService
        implements BeanNameAware {

    @Override
    public void setBeanName(String name) {

        System.out.println(name);

    }

}

Spring 会告诉:

UserService

↓

你在Spring里面叫什么名字

可以简单记:

Aware

=

让Bean知道Spring容器的信息

这个阶段:

知道即可。


七、第四步:BeanPostProcessor 前置处理 ⭐⭐⭐⭐⭐

BeanPostProcessor:

中文:

Bean 后置处理器。

虽然名字叫:

后置处理器

但是它有:

初始化前处理

初始化后处理。


核心方法:

postProcessBeforeInitialization()

表示:

初始化之前处理

流程:

Bean

↓

BeanPostProcessor

↓

初始化前处理

八、第五步:初始化 Bean ⭐⭐⭐⭐⭐

属性注入完成后:

开始执行初始化逻辑。

例如:

@PostConstruct
public void init() {

    System.out.println("初始化");

}

可以做:

加载配置

初始化缓存

准备资源

检查参数

例如:

@Service
public class UserService {

    @Autowired
    private OrderService orderService;


    @PostConstruct
    public void init() {

        System.out.println(
            "UserService初始化完成"
        );

    }

}

执行顺序:

new UserService()

↓

注入OrderService

↓

执行@PostConstruct

九、实例化和初始化区别 ⭐⭐⭐⭐⭐

这是面试容易问的。

实例化

new UserService();

作用:

创建对象

初始化

例如:

@PostConstruct

作用:

对象已经创建

+

依赖已经注入

↓

执行初始化逻辑

所以:

实例化

↓

对象出现


初始化

↓

对象准备好使用

可以理解成:

实例化:

房子盖出来


属性填充:

家具搬进去


初始化:

检查水电、设备


Bean完成:

可以入住

十、第六步:BeanPostProcessor 后置处理 ⭐⭐⭐⭐⭐

初始化完成后:

执行:

postProcessAfterInitialization()

流程:

初始化完成

↓

BeanPostProcessor

↓

初始化后处理

这个阶段非常重要。

因为:

Spring 很多功能:

AOP

@Transactional

@Async

都和 Bean 后置处理机制密切相关。


十一、BeanPostProcessor 为什么重要?

假设:

@Service
public class UserService {

    @Transactional
    public void save() {

    }

}

最开始:

new UserService()

得到:

原始UserService

但是:

因为:

@Transactional

Spring 可能需要:

创建代理对象。

最终:

UserService代理对象
        |
        ↓
原始UserService

其他 Bean 注入的:

可能是:

代理对象

而不是最开始:

new出来的原始对象

所以:

BeanPostProcessor

是 Spring 非常重要的扩展机制。


十二、Bean 创建完成

经过:

实例化

↓

属性填充

↓

Aware

↓

初始化前处理

↓

初始化

↓

初始化后处理

Bean:

正式创建完成。


对于普通单例 Bean:

最终会进入:

singletonObjects

也就是:

一级缓存。


这和昨天学的三级缓存对应:

一级缓存

singletonObjects

↓

保存完整单例Bean

十三、Bean 正常使用

创建完成之后:

其他 Bean 可以:

@Autowired
private UserService userService;

获取它。

或者:

applicationContext.getBean(UserService.class);

此时:

Bean 处于:

正常使用阶段

十四、Bean 销毁

当:

Spring容器关闭

Bean 会进入销毁阶段。

例如:

@PreDestroy
public void destroy() {

    System.out.println("销毁");

}

可以执行:

释放资源

关闭连接

停止线程

清理数据

流程:

Spring关闭

↓

@PreDestroy

↓

Bean销毁

十五、完整 Bean 生命周期 ⭐⭐⭐⭐⭐

把这张图记住:

Spring启动
    ↓
实例化Bean
    ↓
new UserService()
    ↓
属性填充
    ↓
@Autowired依赖注入
    ↓
Aware回调
    ↓
BeanPostProcessor
初始化前处理
    ↓
@PostConstruct等初始化
    ↓
BeanPostProcessor
初始化后处理
    ↓
Bean创建完成
    ↓
单例Bean进入一级缓存
    ↓
正常使用
    ↓
Spring容器关闭
    ↓
@PreDestroy
    ↓
Bean销毁

十六、Bean生命周期和三级缓存的关系 ⭐⭐⭐⭐⭐

你前面学过:

一级缓存

二级缓存

三级缓存

三级缓存主要发生在:

Bean创建过程中

关系:

Bean生命周期
      |
      ↓
    实例化
      |
      ├────→ 提前暴露
      |        ↓
      |      三级缓存
      |        ↓
      |      循环依赖
      |
      ↓
   属性填充
      ↓
    初始化
      ↓
BeanPostProcessor
      ↓
   AOP代理
      ↓
   完整Bean
      ↓
   一级缓存

所以:

循环依赖不是独立知识点。

它实际上发生在:

Bean 生命周期创建阶段。


十七、Bean生命周期和AOP关系

例如:

@Transactional
public void save() {

}

Spring:

实例化原始Bean

↓

依赖注入

↓

初始化

↓

BeanPostProcessor处理

↓

创建AOP代理

↓

最终Bean

所以:

你从 Spring 容器拿到的:

UserService

可能实际上是:

代理对象

这也是为什么:

@Transactional

@Async

AOP

和 Bean 生命周期关系非常密切。


🎤 面试回答(30秒)

Spring Bean 的生命周期主要包括实例化、属性填充、Aware 回调、BeanPostProcessor 初始化前处理、初始化、BeanPostProcessor 初始化后处理、正常使用以及销毁。

Spring 首先实例化 Bean,然后进行依赖注入,之后执行相关 Aware 回调和初始化方法。在初始化前后 BeanPostProcessor 可以对 Bean 进行扩展处理,AOP 代理等功能就和这个扩展机制密切相关。Bean 创建完成后交给 Spring 容器管理,容器关闭时执行销毁逻辑。


🎯 面试追问

Q1:Bean 生命周期有哪些阶段?

答:

实例化

↓

属性填充

↓

Aware

↓

BeanPostProcessor前置

↓

初始化

↓

BeanPostProcessor后置

↓

使用

↓

销毁

Q2:实例化和初始化有什么区别?

答:

实例化:

new对象

初始化:

依赖注入完成以后
执行初始化逻辑

Q3:为什么实例化以后 @Autowired 属性还是 null?

答:

因为:

实例化

和

属性填充

是两个阶段。

先 new 对象:

再进行依赖注入。


Q4:BeanPostProcessor 是什么?

答:

Spring 提供的 Bean 扩展机制,可以在 Bean 初始化前后对 Bean 进行处理。


Q5:BeanPostProcessor 和 AOP 有什么关系?

答:

AOP 代理的创建和 BeanPostProcessor 机制密切相关,Spring 可以在 Bean 创建过程中将原始 Bean 包装成代理对象。


Q6:@PostConstruct 什么时候执行?

答:

依赖注入完成之后:

Bean 初始化阶段执行。


Q7:@PreDestroy 什么时候执行?

答:

Spring 容器关闭、Bean 销毁之前执行。


Q8:Bean 生命周期和循环依赖有什么关系?

答:

Spring Bean 的实例化和属性填充是两个阶段,所以 Bean 实例化后可以提前暴露引用,让其他 Bean 使用,从而解决部分循环依赖。


Q9:完整单例 Bean 最终放在哪里?

答:

一级缓存

singletonObjects

⚠️ 工作踩坑

1. 在构造方法里使用 @Autowired 对象

例如:

@Autowired
private OrderService orderService;

public UserService() {

    orderService.query();
}

此时:

orderService可能还是null

因为:

构造方法执行

↓

对象实例化

↓

之后才进行@Autowired依赖注入

如果需要依赖注入完成后执行逻辑:

可以考虑:

@PostConstruct

2. 认为 new 出来就是完整 Bean

错误。

new UserService()

只是:

实例化

后面还有:

依赖注入

初始化

BeanPostProcessor

等过程。


3. 自己 new Spring Bean

例如:

UserService userService =
        new UserService();

这个对象:

不是 Spring 容器创建的。

所以不会自动经历完整的 Spring Bean 管理流程。

例如:

@Autowired

@Transactional

@Async

AOP

等 Spring 能力可能不会按预期生效。


❓ 自测

  1. 什么是 Spring Bean 生命周期?

  2. Bean 生命周期主要有哪些阶段?

  3. 什么叫实例化?

  4. 什么叫属性填充?

  5. 实例化和初始化有什么区别?

  6. 为什么刚 new 出来的 Bean 中 @Autowired 属性可能还是 null?

  7. Aware 是干什么的?

  8. BeanPostProcessor 是干什么的?

  9. @PostConstruct 在什么时候执行?

  10. @PreDestroy 在什么时候执行?

  11. BeanPostProcessor 和 AOP 有什么关系?

  12. Bean 生命周期和循环依赖有什么关系?

  13. 为什么字段循环依赖有机会通过提前暴露解决?

  14. 完整的单例 Bean 最终放在哪个缓存?

  15. 为什么自己 new 的对象和 Spring 管理的 Bean 不一样?


评论