SpringBoot特定场景下使用DevTools导致的bug

我明明在这

给这个全局变量设置了一个值

紧接着在这打印的时候他就为空

虽然在这没有直接打印哈

但这里边也很简单

就直接return了一个MyTool1.value

大家看 我们试一下啊

大家看,现在这个MyTool1.value是有值的

但是呢

我们执行下边这个代码的时候

我们看他就返回一个null

那为什么会这样呢

我先给大家介绍一下这个项目背景哈

那为了准备这个demo

我把一些不相关的业务代码都删掉了

这里边有两个重点

第一个重点是

这 MyTool1 和 MyTool2

都在这个第三方的jar包里

这第三方jar包

也是我为了准备demo封装的,也很简单

MyTool1里边就一个全局的静态变量

MyTool2 呢就分别取

和设置这个MyTool1的静态变量

把它安装到Maven库里

然后回到这个项目

在Maven引用之后呢

我又覆盖了一下MyTool1

那这里边原本我们是做了一些扩展

但是呢

这些扩展对于这次 bug 没有什么影响

所以呢这块我就用注释意思一下

其实这里边代码

跟覆盖之前的代码是一模一样的

好这是第一个重点

第二个重点呢就是

这个项目用到了SpringBoot的

DevTools

为什么用到它就会有问题呢

我们先来看一下这个图

嗯 DevTools 为了实现这个热部署

他自己自定义了一个叫 Restart ClassLoader的

这么一个类加载器

那这个 ClassLoader 主要是加载了一些

我们项目里自己写的这些类文件

我们引的第三方的jar包的类文件

他不负责加载

所以呢

我们再回过头看这个MyTool1和Tool2

Tool1 因为我们在项目里写了

所以呢这个 DevTools 他会加载

MyTool1

当然了他还会加载

其他的我这里边就不写了哈

只要是我们这个项目的这些代码文件

他都会加载

那这个 ApplicationClassLoader 呢

他是都加载

包括这个MyTool1

MyTool2

好这就相当于什么呢相当于

这个MyTool1

这个类有两个

大家看在这个DevTools里面有一个

然后在这 AppClassLoader 里面还有一个

包括我们平时写的这些 controller

啊这些代码

他在本地启动的时候

他用的都是这个DevTools

加载的这些类

所以呢

我们在这

controller里边直行的时候

注意这行代码

这块直行的时候他用到的是

DevTools加载的这个

Controller 那么他在取

MyTool1 的时候他就近他就会取到

这个MyTool

也就是说他在给这个 value 复制的时候

付的是这个MyTool1

然后呢我们下边取MyTool2.getValue()的时候

因为MyTool2在这找不到

对吧啊他就会向上找找到这个

AppClassLoader的MyTool2

然后在执行MyTool2里边的方法的时候

他又是就近找到了这个MyTool1

所以呢他是取不到的

(他俩是不一样的)

那我们其实可以这样验证一下哈

我在

这个重写的地方加一个 static 块

然后呢我们输出一下什么呢

MyTool.class.getClassLoader()

好我们来试一下哈

我在第一行打断点

清一下啊

打开我现在执行一下

(单步跳过)

大家看

他现在用到的这个MyTool1

是 ResstartClassLoader 加载的

好我们再往里走

我们在这再打断点

然后呢单步跳过

大家看

这个就是 AppClassLoader

那了解了他的原理以后我们也能猜到

如果我们把这个

项目打包成

jar包来运行的时候其实就没问题了

我们来试一下

ok 然后呢

我们启动这个jar包

他在target里边

ok 我们再来试一下哈

大家看这就可以了

这也不是刚才

那个 RestartClassLoader 了

那如果在本地调试

碰上这种极端情况呢

我们就可以把这个

去掉把这依赖去掉就可以了

我们再试一下

啊!这块导入一下重新来 (修改了pom.xml文件)

我们再试一下

大家看,这就可以了

那网上我也找到了一些方法

说是可以在项目里边做一些配置

但是那个配置哈我没配成功

所以等下次我配置明白了

再给大家分享

最后更新于