spring 默认创建的单例 bean 是全局共享的,若在其中修改可变状态(如实例变量),将导致多线程间数据污染,破坏应用稳定性;正确做法是保持 bean 无状态,或使用 threadlocal、作用域(如 prototype)隔离上下文。
在 Spring 应用中,绝大多数 Bean(如 @Service、@Repository、@Component)默认以 singleton 作用域创建——即整个 Spring 容器中仅存在一个实例,被所有请求、线程和组件共享。这意味着:对该 Bean 实例成员变量(非 final、非线程安全类型)的任何修改,都会直接影响其他并发调用的行为。
例如,以下代码存在严重线程安全问题:
@Service
public class UnsafeContextService {
private String currentUser; // ❌ 危险:共享可变状态
public void setCurrentUser(String user) {
this.currentUser = user; // 多线程调用会互相覆盖
}
public String getCurrentUser() {
return currentUser;
}
}
当两个 HTTP 请求(由不同线程处理)先后调用 setCurrentUser(“A”) 和 setCurrentUser(“B”) 时,currentUser 的值可能被任意覆盖,后续调用 getCurrentUser() 返回结果不可预测——这正是典型的竞态条件(Race Condition)。
✅ 正确实践包括:
-
保持 Bean 无状态(Stateless):只依赖方法参数和不可变对象,避免在单例 Bean 中存储请求/用户相关数据;