最近在研究Spring Boot的的时候,遇到一个问题。
项目里有一个静态常量类,其中有个常量是可变的,需要项目启动的时候请求外部链接拿到数据后再回调设置这个常量,而这个请求外部链接的操作是通过一个引入的第三方jar包实现的。这个时候出现一个很诡异的现象,项目启动的时候第三方jar包正常执行了请求成功拿到数据,也把这个常量修改好了,但是在之后项目在接收到后端请求需要使用这个常量的时候,却发现这个常量根本就没有被设置过值。

折腾了一会,初步定位原因应该是ClassLoader不一致导致的,于是带着关键字搜索了一番,很幸运的找到了一个虽然问题表现出来的不一样,但是原因是一样的帖子,恰好解决了这个问题。

原来Spring Boot官方文档里有这么一段话:

By default, any open project in your IDE will be loaded using the “restart” classloader, and any regular .jar file will be loaded using the “base” classloader. If you work on a multi-module project, and not each module is imported into your IDE, you may need to customize things. To do this you can create a META-INF/spring-devtools.properties file.

The spring-devtools.properties file can contain restart.exclude. and restart.include. prefixed properties. The include elements are items that should be pulled up into the “restart” classloader, and the exclude elements are items that should be pushed down into the “base” classloader. The value of the property is a regex pattern that will be applied to the classpath.

就是说使用了spring-boot-devtools这个依赖,默认启动的时候会使用RestartClassLoader这个ClassLoader类加载class,但是以jar形式引入的class会使用基础的ClassLoader(也就是AppClassLoader)加载。

这么一看就立马明白了,打了断点日志输出一看 ,果不其然

第三方jar包设置值时常量类的ClassLoader信息

类加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
类加载器:sun.misc.Launcher$ExtClassLoader@185d8b6

使用时常量类的ClassLoader信息

类加载器:org.springframework.boot.devtools.restart.classloader.RestartClassLoader@3055b483
类加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
类加载器:sun.misc.Launcher$ExtClassLoader@185d8b6

既然是这样,文档里也说了怎么解决这个问题,于是照做,把对应的jar名称加入到META-INF/spring-devtools.properties文件

META-INF/spring-devtools.properties

restart.include.thirdparty=/thirdparty-1.1.1.jar

重启后就正常了。

参考链接:使用了Spring boot devtools, dozer转换嵌套对象失败解决记录


MartinDai
1.5k 声望236 粉丝

保持学习心态,持续成长