Bean是安全的么

Bean安不安全这个取决于其状态以及作用域

我们这里以常用的两种作用域single以及prototype做介绍。几乎所有的应用场景都是默认的single,所以我们

重点关注single就好

像prototype这种就是每次getBean时拿的都是一个新的Bean,那么像这种就是就不存在竞争问题,即是安全

而single作用域下,ioc容器拥有唯一的Bean实例。可能存在资源竞争问题,取决于Bean是否有状态。如果这

个Bean是有状态的,那么就存在线程安全的问题,这里的有无状态指的是是否包含可变的成员变量

不过,大部分 Bean 实际都是无状态(没有定义可变的成员变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。对于有状态单例 Bean 的线程安全问题,常见的有两种解决办法:

1.在 Bean 中尽量避免定义可变的成员变量。

2.在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

即使是无状态的bean也不一定线程安全,可能还需要考虑你的方法有没有涉及到其它类的静态成员变量的资源竞争

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class UserCacheService {
private static final Map<Long, String> userCache = new HashMap<>();

public void put(Long id, String name) {
userCache.put(id, name); // HashMap 非线程安全
}

public String get(Long id) {
return userCache.get(id);
}
}

map线程不安全的,用cmap就好了