必杀技:当报错信息看不出原因时,怎么办?

猿天地 2020-06-06 00:40:18
原文地址:https://segmentfault.com/a/1190000022422991

今天遇到了一个错误,一般的错误提示会很明显,一看就知道是什么问题。今天遇到的这个说实话真的不好找原因,一般在这种情况下该怎么解决呢?

分享下我的思路吧,不一定是最好的,至少有用。

直接上图吧,下面是报错信息:

![q1.png](https://segmentfault.com/img/bVbGfoW "q1.png")

为了方便查看,我把最重要的信息提取出来,如下:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [com/cxytiandi/kitty/web/config/WebAppConfigurer.class]: Invocation of init method failed; nested exception is java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy

java.lang.ArrayStoreException这个确实平时很少遇到,看了下源码,这个是数组存储异常。比如下图中我框起来的部分就清楚的表示了在什么场景下会出现这个异常。

![q2.png](https://segmentfault.com/img/bVbGfo0 "q2.png")

也就是在存储的时候类型不一致,然后就报错了呗!

第二个需要关注的错误信息是WebAppConfigurer.class,这个还算挺明确的,告诉我哪个类有问题,然后我看了下对应的代码,也就手动的映射了资源路径而已。

![q3.png](https://segmentfault.com/img/bVbGfo1 "q3.png")
于是我就想,是不是这里面哪个类加载的时候出问题了,我把WebAppConfigurer直接去掉了,但是并没什么用,后面还是报的相同的错误,只不过是提示另一个类了,就是WebMvcAutoConfiguration。

[org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy

所以说这些错误信息没能直接定位问题就是这个原因,我们要关注的还是java.lang.ArrayStoreException这个异常,只要找到这个异常发生的地方就能解决了。

下面只能借助于IDEA强大的调试功能了,增加一个Java Exception Breakpoints了。

![q4.png](https://segmentfault.com/img/bVbGfo4 "q4.png")

然后debug模式重启,果不其然就报错的时候就进断点了。

![q5.png](https://segmentfault.com/img/bVbGfo6 "q5.png")

![q6.png](https://segmentfault.com/img/bVbGfo7 "q6.png")

这下终于找到原因了,parseClassValue的时候出问题了,Class就是 org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration。

这个类是我当时在Sleuth中扩展Sentinel对Feign支持的时候做了一些修改,没想到居然出了Bug。

下面给大家说明下真正的原因吧,在这个扩展模块中sentinel的依赖是可选的,如下:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel</artifactId>
    <optional>true</optional>
</dependency>

刚好报错的项目中不需要用到Sentinel,但是用到了Sleuth和Feign,所以TraceFeignClientAutoConfiguration生效了。主要还是Conditional都满足条件了。
![q7.png](https://segmentfault.com/img/bVbGfpb "q7.png")
项目中又没显示指定依赖Sentinel,这个类自然加载失败。

所以解决办法就是要么加Sentinel依赖,要么就是在@ConditionalOnClass中加上Sentinel的类,这样只有当在Sentinel的类在classpath中存在的时候才会加载,如果项目没依赖Sentinel那么就不加载,这样就没问题了。

![q8.png](https://segmentfault.com/img/bVbGfph "q8.png")
最后总结下吧,主要还是要找到真正问题发生在什么地方,有的时候异常信息给出的并不一定是真正的地方,只是有关联而已。

当你封装的模块设置了optional=true的时候,在对应的配置类加载生效也需要用@ConditionalOnClass来进行判断启用,否则就会出现上面的问题。

关于作者:尹吉欢,简单的技术爱好者,《Spring Cloud微服务-全栈技术与案例解析》, 《Spring Cloud微服务 入门 实战与进阶》作者, 公众号 猿天地 发起人。

声明:该文章系转载,转载该文章的目的在于更广泛的传递信息,并不代表本网站赞同其观点,文章内容仅供参考。

本站是一个个人学习和交流平台,网站上部分文章为网站管理员和网友从相关媒体转载而来,并不用于任何商业目的,内容为作者个人观点, 并不代表本网站赞同其观点和对其真实性负责。

我们已经尽可能的对作者和来源进行了通告,但是可能由于能力有限或疏忽,导致作者和来源有误,亦可能您并不期望您的作品在我们的网站上发布。我们为这些问题向您致歉,如果您在我站上发现此类问题,请及时联系我们,我们将根据您的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。