面试知识库
基础

Spring-Bean作用域#

一句话答案#

Spring Bean 默认 Singleton(单例),还支持 Prototype(每次 new)、Request、Session、Application 五种作用域,Web 环境下后三种才可用。

核心要点

五种作用域#

作用域含义生命周期
singleton容器中只有一个实例(默认)随容器创建和销毁
prototype每次 getBean() 创建新实例容器不管理销毁,由调用方负责
request每个 HTTP 请求一个实例请求结束时销毁
session每个 HTTP Session 一个实例Session 过期时销毁
application每个 ServletContext 一个实例应用关闭时销毁

Singleton 与 Prototype 对比#

维度SingletonPrototype
实例数1 个每次请求新建
线程安全需要自己保证(无状态设计)天然线程安全(各用各的)
销毁回调容器调用 @PreDestroy容器不负责,需手动管理
性能好(复用)差(频繁创建)

Singleton Bean 注入 Prototype Bean 的问题#

@Component  // 默认 Singleton
public class SingletonBean {
    @Autowired
    private PrototypeBean proto;  // 注入时只创建一次!后续用的都是同一个实例
}
java

问题: Singleton Bean 只初始化一次,注入的 Prototype Bean 也只创建一次,后续调用用的都是同一个实例。

解决方案:

  1. @Lookup 注解:让 Spring 每次调用时动态创建 Prototype
  2. ObjectFactory / Provider@Autowired ObjectFactory<PrototypeBean> factory; 每次调 factory.getObject()
  3. ApplicationContext.getBean():手动从容器获取

实际使用场景#

  • Singleton:无状态的 Service、DAO、Controller(99% 的 Bean)
  • Prototype:有状态的对象(如每次请求需要独立的处理器实例)
  • Request:存储当前请求的用户信息
  • Session:购物车
面试回答(2分钟版)

Spring Bean有五种作用域。Singleton是默认的,整个容器只有一个实例,随容器启动创建和关闭销毁,99%的Service、DAO、Controller都用这种。Prototype是每次getBean都创建新实例,容器不负责销毁需要调用方自行管理。Request、Session和Application是Web环境专用的,分别对应每个HTTP请求、每个会话和整个ServletContext一个实例。面试最常考的坑是Singleton注入Prototype的问题:因为Singleton只初始化一次,注入的Prototype也只创建一次,后续用的都是同一个实例,违背了Prototype的本意。解决方案有三种:用@Lookup注解让Spring每次动态创建、用ObjectFactory或Provider每次调getObject获取新实例、或者直接通过ApplicationContext.getBean手动获取。另外Singleton Bean不是线程安全的,如果有状态字段需要用ThreadLocal或同步机制自行保证。

追问与易错

追问方向:

  • “Singleton Bean 线程安全吗?”→ 不是,需要自己保证(无状态 / ThreadLocal)
  • “Prototype Bean 的销毁谁管?”→ 容器不管,需自己调用或用 DestructionAwareBeanPostProcessor

易错点:

  • ❌ “Singleton 就是线程安全的”——单例 ≠ 线程安全,有状态字段需同步
  • ❌ “Prototype 注入到 Singleton 还是每次新建”——不是,只在注入时创建一次