单例 bean 与原型 bean 的核心区别在于实例复用策略:单例仅创建一次并全局共享,原型每次请求均新建独立实例;单例生命周期由容器全程托管,原型初始化后由客户端自行管理资源。

单例 Bean 和原型 Bean 的核心区别,在于“同一个 Bean 定义”被容器提供实例时的复用策略:单例只创建一次、反复返回同一实例;原型每次请求都新建一个独立实例。
实例创建时机与数量
单例 Bean 在 Spring 容器启动时(或首次获取时)初始化一次,之后所有注入点或 getBean() 调用都共享这个对象。原型 Bean 每次被注入或主动获取,容器都会执行完整创建流程——包括构造、属性赋值、初始化回调(如 @PostConstruct),生成全新对象。
- 单例:一个定义 → 一个实例 → 全局共用
- 原型:一个定义 → 多个实例 → 各自独立
生命周期管理责任归属
单例 Bean 的整个生命周期(创建、初始化、销毁)均由 Spring 容器全程托管。原型 Bean 的创建和初始化由容器完成,但一旦交给客户端(比如某个 Service 类),容器就不再跟踪它——不会调用 @PreDestroy 或 destroy-method,也不会参与垃圾回收。
- 你用了原型 Bean,就得自己负责释放它持有的资源(如数据库连接、线程池、缓存引用)
- 若需在单例中动态获取新原型实例,不能靠字段注入,得用 方法注入 或
ObjectFactory/Provider
依赖关系中的行为差异
当单例和原型相互依赖时,行为不直观,容易出错:
- 单例依赖原型:字段注入后,该原型实例在单例整个生命周期内固定不变(只注入一次)
- 原型依赖单例:没问题,每个原型实例都持有同一个单例引用
- 原型依赖原型:每次获取新原型时,其内部依赖的其他原型也会一并新建
适用场景判断依据
选单例还是原型,关键看 Bean 是否携带可变状态:
- 无状态工具类(如
JsonUtil、HttpClient配置类)→ 单例,节省资源 - 有状态业务对象(如
ShoppingCart、RequestContext)→ 原型,避免状态污染 - 短生命周期、需隔离上下文的对象(如 DTO 构建器、临时任务处理器)→ 原型更安全











