实力挖坑,当spring bean装配遇到错误的自定义ClassLoader实现

拈花ヽ惹草 提交于 2020-04-07 04:13:41

实现了一个功能FeatureA,该功能是注入到webappB中执行的。

FeatureA实现的时候使用了elasticsearch client,该版本的client所依赖的log类库版本跟webappB使用的log类库冲突。于是自定义ClassLoader加载FeatureA的class进行隔离。

之前好好的,直到前不久webappB新版本引入了esclient jar,版本跟FeatureA所使用的不一样。

然后FeatureA加载的时候就出错了,错误关键堆栈信息如下:

Caused by: java.lang.IllegalStateException: Method [isLoopbackAddress] was discovered in the .class file but cannot be resolved in the class object
at org.springframework.core.LocalVariableTableParameterNameDiscoverer$LocalVariableTableVisitor.resolveMember(LocalVariableTableParameterNameDiscoverer.java:251)
at org.springframework.core.LocalVariableTableParameterNameDiscoverer$LocalVariableTableVisitor.visitEnd(LocalVariableTableParameterNameDiscoverer.java:234)
at org.springframework.asm.ClassReader.readMethod(ClassReader.java:1172)
at org.springframework.asm.ClassReader.accept(ClassReader.java:729)
at org.springframework.asm.ClassReader.accept(ClassReader.java:527)
at org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass(LocalVariableTableParameterNameDiscoverer.java:116)
at org.springframework.core.LocalVariableTableParameterNameDiscoverer.getParameterNames(LocalVariableTableParameterNameDiscoverer.java:89)
at org.springframework.core.PrioritizedParameterNameDiscoverer.getParameterNames(PrioritizedParameterNameDiscoverer.java:67)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1274)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1131)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:541)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501)
... 53 more

 

这一看就是类冲突了,不过明明使用ClassLoader隔离了啊,应该是自定义ClassLoader实现有问题吧导致类加载优先级不符合预期吧。

沿着这个思路想当然的去看loadclass相关的方法调用,排查……一无所获。

 

再次仔细看错误堆栈

asm?

这个显然是读取class字节码的。

spring装配的时候读取字节码干啥了?

应该是为了做代理实现aop,spring是通过修改字节码实现aop的。 

等等……那spring是怎么获取到字节码的了,应该是通过ClassLoader.getResource咯……我当时偷懒没重写getResource方法。

默认实现是parent优先,那就会获取到webappB里的esclient class字节码。

 

重写getResource,果然问题解决。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!