spring-boot-devtools 不同ClassLoader引起的问题

问题场景:因业务需求,需要在请求到达接口时,进行IP获取。并且需要根据IP进行相关处理,由于其它系统有使用到的可能,于是在外部新创建了一个jar包,在该jar包中使用FeignClient的方式,调用业务接口,具体实现如下:

 

 

然后在具体需要拦截IP的方法上,加上该注解。
然后再在启动类上,添加该jar包的扫描。
启动服务。
突然发现,服务启动失败,并提示 实例化CheckIpAspect失败,原因是,找不到DataSyncServiceApi这个Bean。按照往常的经验,是没有添加该Api的包扫描,于是去启动类检查。
但是,很不辛的是,@EnableFeignClients上是加了这个类的包扫描的。
那说明,不是包扫描的问题。
突然想起另一个服务也加了拦截IP的注解,于是抱着尝试的心态,启动了一下。结果居然成功了。
仔细对比两个启动类上的配置。
发现出问题的服务多了一个注解
@EnableCheckFeign ,这个注解是我们项目的准入系统的一部分。
于是我把这个注解去掉,发现还是相同的错误。
那么可以判定不是这个注解的原因。
于是我把jar包中的DataSyncServiceApi添加@Lazy 改为懒加载。
这次能成功启动了,我再调用加了注解的方法,这个时候抛出了一个异常,具体内容为:
interface ‘xxxxxxx’ is not visible from class loader
提示这个接口在类加载器加载之后 是不可见的
那是因为jar包中使用的类加载器和服务中使用的类加载器不同吗?
这个服务的唯一特殊之处在于引入了准入的jar包,于是我根据依赖树,果然发现了一个模块Spring-boot-devtools,这是热部署模块,而这个模块的类加载器确实和普通的类加载器不同:
一个RestartClassLoader,一个普通的AppClassLoader
。。。。。
由此也可以分析出,为什么不设置为懒加载时,会一直提示找不到DataSyncServiceApi,因为类加载器不同,不同的类加载器加载出来的文件互相不可见,此时jar包要使用服务中加载的类就无法获取到。
 
解决方案:
1.将jar包的类加载器改为热部署的类加载器
2.服务中移除Spring-boot-devtools

posted on 2020-09-07 15:24  月满清爵  阅读(605)  评论(0编辑  收藏  举报