今天在开发项目组遇到了一个奇怪的问题。
一、现象
共通工具类中使用饿汉单例模式创建对象。
public class DemoManager {
@Autowired
private RedisUtil redisUtil;
private static DemoManager instance = null;
public static DemoManager getInstance() {
if (instance == null) {
synchronized (DemoManager.class) {
instance = new DemoManager();
}
}
return instance;
}
}
这种工具类中用到了 RedisUtil 在项目启动时 它是正常可以读取写入的,但是启动成功后,外部服务层代码通过DemoManager.getInstance()这个方法调用的目标instance时,类中的redisUtil 为null 报出了空指针异常。
二、分析原因
1.饿汉单例模式特点静态加载。
2.静态加载优先于spring容器加载。
3.大致可以理解为static创建的instance对象中redisUtil 是优先于容器创建出来的,所以为空很正常。
三、如何解决
方案1.简单粗暴的解决办法,在容器初始化时给instance对象赋值this.redisUtil;
方案2.修改为懒汉单例模式(在此业务场景不适合,因为大量外部调用都是直接调用static的该对象)
四、测试方案是否可行
修改后代码为