【Spring】Bean的生命周期详解

一文彻底搞懂 Spring Bean(概念、生命周期、作用域、常见注解、源码原理、面试重点)


在 Spring 开发中,我们每天都会写:

java 复制代码
@Service
public class UserService {}

@Autowired
private UserService userService;

但很多人其实并没有真正理解:

  • Bean 到底是什么?
  • Spring 是如何创建 Bean 的?
  • Bean 生命周期有哪些阶段?
  • @Autowired 是如何注入的?
  • 单例 Bean 是线程安全吗?
  • Bean 是什么时候创建的?

本篇文章将系统讲清 Spring Bean 的核心知识体系


一、什么是 Bean?

1 Bean 的概念

Spring 中,Bean 就是被 Spring 容器管理的对象

简单理解:

Bean = 由 Spring 创建 + 管理 + 注入 的对象

例如:

java 复制代码
@Service
public class UserService {}

Spring 在启动时会:

  1. 扫描到 @Service
  2. 创建 UserService 对象
  3. 存入容器
  4. 其他类可以通过 @Autowired 使用

这个对象就是 Bean


2 为什么需要 Bean?

如果没有 Spring:

java 复制代码
UserService userService = new UserService();

会出现问题:

  • 对象创建需要自己管理
  • 对象依赖关系复杂
  • 对象生命周期无法统一管理

而 Spring 通过 **IoC(控制反转)**解决了这些问题。

核心思想:

复制代码
对象不由程序员创建
而是交给 Spring 容器创建

因此:

复制代码
Bean = IoC 容器中的对象

二、Bean 的创建方式

Spring 创建 Bean 有多种方式。


1 注解方式(最常用)

Spring Boot 开发基本使用注解。

常见注解:

注解 作用
@Component 通用组件
@Service Service层
@Repository DAO层
@Controller 控制层
@RestController REST接口

示例:

java 复制代码
@Service
public class UserService {
}

启动时 Spring 会自动扫描并注册 Bean。


2 @Bean 方式

适合:

  • 第三方对象
  • 配置类

示例:

java 复制代码
@Configuration
public class AppConfig {

    @Bean
    public UserService userService() {
        return new UserService();
    }

}

Spring 会把 userService() 的返回值注册为 Bean。


3 XML 配置(老项目)

早期 Spring 使用 XML:

xml 复制代码
<bean id="userService" class="com.demo.UserService"/>

现在基本不用。


三、Bean 的作用域(Scope)

Spring Bean 默认是单例

1 singleton(默认)

java 复制代码
@Scope("singleton")

特点:

  • 容器中只有 一个对象
  • 所有地方共享

示例:

复制代码
Controller -> Service -> Dao

三者使用同一个 Bean

优点:

  • 节省内存
  • 提高性能

2 prototype(多例)

java 复制代码
@Scope("prototype")

特点:

  • 每次获取 Bean 都创建新对象

示例:

java 复制代码
@Autowired
UserService userService;

每次注入得到不同对象。


3 其他 Web 作用域

scope 说明
request 每个请求
session 每个会话
application 整个应用

四、Bean 生命周期(重点)

Spring Bean 生命周期是面试高频题

完整流程如下:

复制代码
1 BeanDefinition 注册
2 Bean 实例化
3 属性注入
4 Aware 回调
5 BeanPostProcessor 前置处理
6 初始化方法
7 BeanPostProcessor 后置处理
8 Bean 可用
9 容器关闭
10 Bean 销毁

我们逐步解释。


1 BeanDefinition 注册

Spring 启动时会:

  • 扫描注解
  • 解析 XML
  • 注册 BeanDefinition

BeanDefinition 是:

复制代码
Bean 的定义信息

包括:

  • class
  • scope
  • lazy
  • initMethod

2 Bean 实例化

Spring 使用反射创建对象:

java 复制代码
UserService userService = new UserService();

3 属性注入

例如:

java 复制代码
@Autowired
private OrderService orderService;

Spring 会进行:

复制代码
依赖注入 DI

4 Aware 接口回调

如果 Bean 实现了:

复制代码
BeanNameAware
BeanFactoryAware
ApplicationContextAware

Spring 会回调。

例如:

java 复制代码
public class DemoBean implements BeanNameAware {

    @Override
    public void setBeanName(String name) {
        System.out.println(name);
    }
}

5 BeanPostProcessor 前置处理

Spring 提供扩展机制:

复制代码
BeanPostProcessor

可以在 Bean 初始化前进行处理。

例如:

复制代码
AOP

6 初始化方法

初始化方法有三种:

1 @PostConstruct

java 复制代码
@PostConstruct
public void init(){
}

2 InitializingBean

java 复制代码
public class DemoBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
    }

}

3 initMethod

java 复制代码
@Bean(initMethod = "init")

7 BeanPostProcessor 后置处理

Spring 会再次调用:

复制代码
postProcessAfterInitialization

例如:

复制代码
AOP代理生成

8 Bean 可使用

此时 Bean 已经可以正常使用。


9 容器关闭

Spring 容器关闭:

复制代码
ApplicationContext.close()

10 Bean 销毁

销毁方法:

1 @PreDestroy

java 复制代码
@PreDestroy
public void destroy(){
}

2 DisposableBean

java 复制代码
public void destroy()

五、Bean 生命周期总结(面试版)

Spring Bean 生命周期:

复制代码
1 BeanDefinition 注册
2 实例化
3 属性注入
4 Aware回调
5 BeanPostProcessor before
6 初始化
7 BeanPostProcessor after
8 Bean使用
9 容器关闭
10 Bean销毁

面试回答建议简化为:

复制代码
实例化 -> 依赖注入 -> 初始化 -> 使用 -> 销毁

六、Bean 依赖注入

Spring 注入 Bean 常见方式:


1 @Autowired

最常用。

java 复制代码
@Autowired
private UserService userService;

默认 按类型注入


2 @Qualifier

当存在多个 Bean:

java 复制代码
@Autowired
@Qualifier("userServiceImpl")

3 @Resource

JDK 提供。

java 复制代码
@Resource
private UserService userService;

默认 按名称注入


七、Bean 加载时机

Spring Bean 默认:

复制代码
容器启动时创建

称为:

复制代码
Eager Loading

懒加载

java 复制代码
@Lazy
@Service
public class UserService {}

只有使用时才创建。


八、Bean 的循环依赖(高频面试题)

例如:

复制代码
A -> B
B -> A

Spring 使用:

复制代码
三级缓存

解决。

三级缓存:

复制代码
singletonObjects 一级缓存
earlySingletonObjects 二级缓存
singletonFactories 三级缓存

核心作用:

复制代码
提前暴露对象

但只支持:

复制代码
单例 + setter注入

九、Bean 常见易错点

1 @Autowired 失效

原因:

复制代码
对象不是 Spring 管理

错误示例:

java 复制代码
UserService service = new UserService();

解决:

复制代码
必须由 Spring 注入

2 静态变量无法注入

错误:

java 复制代码
@Autowired
static UserService userService;

Spring 不会注入 static。


3 单例 Bean 线程安全问题

Spring Bean 默认:

复制代码
singleton

如果 Bean 内部有:

复制代码
成员变量

可能产生 线程安全问题

解决:

复制代码
避免共享变量

十、Spring Bean 面试高频题


1 什么是 Spring Bean?

答:

复制代码
Spring Bean 是被 Spring IoC 容器管理的对象。

2 Bean 生命周期?

答:

复制代码
实例化 -> 属性注入 -> 初始化 -> 使用 -> 销毁

详细版本:

复制代码
实例化
依赖注入
Aware回调
BeanPostProcessor
初始化
BeanPostProcessor
销毁

3 Bean 默认作用域?

复制代码
singleton

4 如何创建 Bean?

三种:

复制代码
@Component
@Bean
XML

5 Bean 单例线程安全吗?

复制代码
不一定

取决于:

复制代码
是否有共享变量

十一、Spring Bean 总结

Spring Bean 核心知识:

复制代码
Bean = Spring容器管理的对象

核心内容:

复制代码
Bean创建方式
Bean作用域
Bean生命周期
依赖注入
循环依赖

理解 Bean 的本质,其实就是理解:

复制代码
Spring IoC 容器
相关推荐
四维迁跃1 分钟前
c++怎么在写入文件流时通过peek预读功能实现复杂的逻辑判断【实战】
jvm·数据库·python
2301_775148157 分钟前
如何管理RAC归档日志_共享存储中的FRA配置与双节点访问
jvm·数据库·python
Ulyanov11 分钟前
《玩转QT Designer Studio:从设计到实战》 QT Designer Studio组件化开发与UI组件库构建
开发语言·python·qt·ui·雷达电子战系统仿真
词元Max12 分钟前
2.8 pydantic 数据校验:AI 开发的隐形利器
开发语言·人工智能·python
qq_3300379915 分钟前
php怎么实现接口请求日志记录_php如何自动记录入参出参与耗时
jvm·数据库·python
Python私教17 分钟前
Hermes Agent 记忆系统详解:MEMORY.md 与跨会话持久化
python
2401_8653825017 分钟前
各省政务信息化项目验收材料清单汇总及差异分析
java·开发语言·数据库
pele22 分钟前
如何用 contextmenu 事件自定义鼠标右键菜单的显示逻辑
jvm·数据库·python
2301_7735536223 分钟前
怎样禁用phpMyAdmin的控制台历史记录_防凭证与查询留存
jvm·数据库·python
m0_7436239225 分钟前
Go语言怎么实现生产者消费者_Go语言生产者消费者模式教程【精通】
jvm·数据库·python