spring bean线程安全与否取决于作用域和状态设计:singleton默认共享实例,无状态时线程安全,有可变成员变量则不安全;prototype、request、session等作用域因实例隔离而天然安全。

Spring Boot 中的 Bean 作用域(Scope)直接决定了实例的复用方式和生命周期,而线程安全问题本质上不是 Spring 框架“给不给”的保障,而是你是否在共享实例里放了可被并发修改的状态。
singleton 是线程安全的吗?关键看有没有共享可变状态
默认作用域,整个容器只创建一个实例。它本身不线程安全,也不线程不安全——取决于你写什么。
- 如果 Bean 里全是 final 字段、只读配置、无状态方法(比如调用外部服务、处理入参、返回新对象),那多个线程同时调用完全没问题
- 一旦加了可变成员变量(如 private int count = 0;),又没加锁或原子操作,就会出现计数错乱、数据覆盖等问题
- 常见误区:以为“Controller 是单例所以不安全”,其实绝大多数 Controller 只依赖 Service、处理请求参数、返回 DTO,根本没存状态,天然安全
prototype、request、session 天然隔离,但要注意注入陷阱
这三类作用域每次获取都新建实例,各自持有独立状态,因此通常不会因并发访问引发冲突。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
prototype:每次
context.getBean(X.class)或通过ObjectProvider获取都是新对象;但若把它注入到 singleton Bean 里,注入动作只发生一次,后续始终用同一个 prototype 实例——这就破坏了隔离性 -
request/session:Web 环境下由 Spring 的
RequestScope和SessionScope管理,每个请求/会话独享一份;但必须确保使用的是 WebApplicationContext,普通单元测试或非 Web 启动会报错 - 不要在这些 Bean 里缓存跨请求/会话的数据,比如把 request-scoped Bean 的字段赋值给 static 变量,就等于主动制造共享
application 和 singleton 行为一致,但范围更大
application 作用域绑定到 ServletContext,整个 Web 应用共用一个实例,和 singleton 在线程安全层面没有本质区别。
- 它比 singleton 多一层容器边界(跨 Spring 子容器仍可能共享),但只要存在可变状态,同样需要同步保护
- 适合放全局只读配置、应用级缓存(配合
ConcurrentHashMap或Caffeine等线程安全实现) - 避免在里面存用户相关、请求相关、会话相关的动态数据
真正决定线程安全的,从来不是作用域,而是状态管理方式
Spring 不干涉你的字段怎么写,也不会自动帮你加锁。判断一个 Bean 是否线程安全,只看一件事:有没有多个线程能同时读写同一块内存(即非 final、非 ThreadLocal、非局部变量的实例字段)。
- 无状态 → 安全(推荐主流做法)
- 有状态 → 选对作用域(prototype/request/session)或加同步(synchronized / ReentrantLock / AtomicInteger)或做线程隔离(ThreadLocal)
- 别依赖“Spring 保证安全”这种幻想,框架只管生命周期,不管业务逻辑的并发控制










