spring 默认创建的单例 bean 是全局共享的,若在其中修改可变状态(如实例变量),将导致多线程间数据污染;正确做法是保持 bean 无状态,或使用 threadlocal、作用域(如 prototype)隔离上下文。
在 Spring 应用中,绝大多数 Bean(如 @Service、@Repository、@Component)默认以 singleton 作用域创建——即整个 Spring 容器中仅存在一个实例,被所有请求、线程和调用共享。这意味着:如果你在某个 HTTP 请求(或任意线程)中修改了该 Bean 的可变实例字段(如 private String currentUser;),该修改会立即对其他并发请求可见,造成严重的线程安全问题和上下文污染。
❌ 危险示例:在单例 Bean 中维护可变状态
@Service
public class OrderService {
private String currentTraceId; // ❌ 共享的可变状态 —— 危险!
public void processOrder(String traceId) {
this.currentTraceId = traceId; // 多线程下互相覆盖!
log.info("Processing with trace: {}", currentTraceId);
// 后续业务逻辑可能误用被覆盖的 currentTraceId
}
}
⚠️ 上述代码在高并发场景下会导致 currentTraceId 被不同请求交替写入,A 请求的日志可能打印出 B 请求的 trace ID,调试与追踪完全失效。
✅ 正确实践:保持 Bean 无状态(推荐)
Spring Bean 应设计为 stateless(无状态):只包含不可变配置、注入的依赖及纯业务逻辑方法,所有请求相关数据应通过方法参数传递: