在 Spring 框架中,Bean 的作用域 决定了 Bean 的生命周期和创建方式。Spring 支持多种作用域,其中最常用的是 单例(Singleton) 和 原型(Prototype)。以下是 Spring 对单例和原型 Bean 的管理流程详解:
1. 单例(Singleton)Bean 的管理流程
- 定义: 单例 Bean 在 Spring 容器中只有一个实例,所有请求共享同一个对象。
- 生命周期: 从容器启动时创建,到容器销毁时销毁。
- 适用场景: 无状态的 Bean,如服务类、工具类等。
管理流程:
-
容器启动:
- Spring 容器启动时,扫描配置(如 XML、注解或 Java Config)并识别需要创建的 Bean。
- 对于单例 Bean,容器会立即创建实例(饿加载)。
-
创建 Bean:
- 调用 Bean 的构造函数创建对象。
- 如果 Bean 依赖其他 Bean,容器会递归创建并注入这些依赖。
-
初始化:
- 调用 Bean 的初始化方法(如
@PostConstruct
注解的方法或init-method
配置)。
- 调用 Bean 的初始化方法(如
-
缓存到容器:
- 将创建的单例 Bean 缓存到 Spring 容器的单例池中。
-
提供服务:
- 每次请求该 Bean 时,容器直接从单例池中返回缓存的实例。
-
容器销毁:
- 当容器关闭时,调用 Bean 的销毁方法(如
@PreDestroy
注解的方法或destroy-method
配置)。
- 当容器关闭时,调用 Bean 的销毁方法(如
示例:
java
@Component
public class MySingletonBean {
public MySingletonBean() {
System.out.println("单例 Bean 被创建了!");
}
@PostConstruct
public void init() {
System.out.println("单例 Bean 初始化完成!");
}
@PreDestroy
public void destroy() {
System.out.println("单例 Bean 被销毁了!");
}
}
2. 原型(Prototype)Bean 的管理流程
- 定义: 每次请求原型 Bean 时,Spring 容器都会创建一个新的实例。
- 生命周期: 由调用者管理,Spring 容器只负责创建,不负责销毁。
- 适用场景: 有状态的 Bean,如用户会话、请求处理类等。
管理流程:
-
容器启动:
- Spring 容器启动时,扫描配置并识别需要创建的 Bean。
- 对于原型 Bean,容器不会立即创建实例,而是延迟到第一次请求时。
-
请求 Bean:
- 每次请求原型 Bean 时,容器都会创建一个新的实例。
-
创建 Bean:
- 调用 Bean 的构造函数创建对象。
- 如果 Bean 依赖其他 Bean,容器会递归创建并注入这些依赖。
-
初始化:
- 调用 Bean 的初始化方法(如
@PostConstruct
注解的方法或init-method
配置)。
- 调用 Bean 的初始化方法(如
-
返回实例:
- 将新创建的 Bean 实例返回给调用者。
-
销毁:
- Spring 容器不会管理原型 Bean 的生命周期,销毁由调用者负责(如调用
@PreDestroy
方法)。
- Spring 容器不会管理原型 Bean 的生命周期,销毁由调用者负责(如调用
示例:
java
@Component
@Scope("prototype")
public class MyPrototypeBean {
public MyPrototypeBean() {
System.out.println("原型 Bean 被创建了!");
}
@PostConstruct
public void init() {
System.out.println("原型 Bean 初始化完成!");
}
@PreDestroy
public void destroy() {
System.out.println("原型 Bean 被销毁了!");
}
}
3. 单例和原型 Bean 的对比
特性 | 单例 Bean | 原型 Bean |
---|---|---|
实例数量 | 容器中只有一个实例 | 每次请求都创建一个新实例 |
生命周期管理 | 由 Spring 容器管理 | 由调用者管理 |
创建时机 | 容器启动时创建(饿加载) | 每次请求时创建(懒加载) |
适用场景 | 无状态的 Bean,如服务类、工具类 | 有状态的 Bean,如会话、请求处理 |
性能 | 启动时可能占用资源,但后续访问快 | 每次请求都有创建开销 |
4. Spring 对单例和原型 Bean 的管理流程总结
- 单例 Bean :
- 容器启动时创建并缓存。
- 所有请求共享同一个实例。
- 生命周期由容器管理。
- 原型 Bean :
- 每次请求时创建新实例。
- 生命周期由调用者管理。
- 容器不缓存实例。
5. 代码示例
单例 Bean
java
@Component
public class SingletonBean {
public SingletonBean() {
System.out.println("单例 Bean 被创建了!");
}
}
原型 Bean
java
@Component
@Scope("prototype")
public class PrototypeBean {
public PrototypeBean() {
System.out.println("原型 Bean 被创建了!");
}
}
测试类
java
@SpringBootApplication
public class MyApp implements CommandLineRunner {
@Autowired
private SingletonBean singletonBean1;
@Autowired
private SingletonBean singletonBean2;
@Autowired
private PrototypeBean prototypeBean1;
@Autowired
private PrototypeBean prototypeBean2;
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
@Override
public void run(String... args) {
System.out.println("单例 Bean 1: " + singletonBean1);
System.out.println("单例 Bean 2: " + singletonBean2);
System.out.println("原型 Bean 1: " + prototypeBean1);
System.out.println("原型 Bean 2: " + prototypeBean2);
}
}
输出:
单例 Bean 被创建了!
原型 Bean 被创建了!
原型 Bean 被创建了!
单例 Bean 1: com.example.SingletonBean@12345
单例 Bean 2: com.example.SingletonBean@12345
原型 Bean 1: com.example.PrototypeBean@67890
原型 Bean 2: com.example.PrototypeBean@54321
希望这能帮助大家理解 Spring 对单例和原型 Bean 的管理流程!如果还有其它问题,欢迎继续讨论。