在Spring框架中,Singleton和Prototype的作用域 与饿汉式/懒汉式的初始化方式是不同维度的概念,它们的关系可以总结为:
1. Singleton Bean 的初始化方式
-
默认是饿汉式 (Eager Loading)
Spring容器启动时就会立即初始化所有非懒加载的Singleton Bean
java@Service // 默认饿汉式Singleton public class OrderService { ... }
-
可显式改为懒汉式 (Lazy Loading)
通过
@Lazy
注解或XML配置lazy-init="true"
,使得Singleton Bean在首次被请求时才初始化。java@Service @Lazy // 懒汉式Singleton public class LogService { ... }
2. Prototype Bean 的初始化方式
-
本质上是懒汉式
因为Prototype Bean每次请求时都会创建新实例,无法在容器启动时预先初始化(否则就违背了"原型"的定义)。
注意: 对Prototype Bean显式配置@Lazy
没有意义,Spring会忽略此配置。
3. 关键结论
作用域 | 是否饿汉式 | 是否懒汉式 |
---|---|---|
Singleton | 默认是(可改为懒汉式) | 可通过@Lazy 实现 |
Prototype | 永远不是 | 本质就是懒汉式 |
4. 常见误区澄清
误区:"Singleton就是饿汉式,Prototype就是懒汉式"
正解:Singleton默认是饿汉式但可配置为懒汉式,而Prototype的初始化行为是固定的(每次请求时懒加载),与Singleton的懒汉式有本质区别:
-
Singleton的懒汉式:整个生命周期只初始化一次(首次请求时)
-
Prototype:每次请求都初始化新实例
5. 代码示例对比
java
// 饿汉式Singleton(默认)
@Component
public class EagerSingleton {
public EagerSingleton() {
System.out.println("EagerSingleton初始化"); // 启动时立即打印
}
}
// 懒汉式Singleton
@Component
@Lazy
public class LazySingleton {
public LazySingleton() {
System.out.println("LazySingleton初始化"); // 首次请求时打印
}
}
// Prototype(天然懒汉式)
@Component
@Scope("prototype")
public class PrototypeBean {
public PrototypeBean() {
System.out.println("PrototypeBean初始化"); // 每次getBean()时打印
}
}
理解这些差异能更精准地控制Spring Bean的生命周期行为。