IDEA Spring 调试器 getResolvableType 异常原因分析
本文档记录业务服务在 IDEA 中启动时抛出 NoSuchMethodException: AnnotatedGenericBeanDefinition.getResolvableType() 的根因与处置方案,供后续遇到同类问题速查。
一、背景
本项目采用 Spring Cloud 微服务架构,技术栈以 Spring Boot 2.1.3.RELEASE / Spring Cloud Greenwich / Spring Framework 5.1.x 为基础,版本统一在项目父 POM 的 <spring-boot.version>2.1.3.RELEASE</spring-boot.version> 中定义。业务主服务的启动主类下文记为 <业务服务主类>。
日常开发中,团队成员习惯在 IntelliJ IDEA 内直接运行/调试各微服务(IDEA 自带 Spring 插件,会在启动时注入一个 com.intellij.spring.debugger.rt 调试运行时,用于在「Spring」工具窗口展示所有 Bean)。该调试运行时的版本随 IDEA 升级而更新,且会按较新版本的 Spring API 反射访问 Bean 元数据——这正是后续问题的伏笔。
二、现象
在 IntelliJ IDEA 中调试/启动业务服务(主类 <业务服务主类>)时,控制台打印如下堆栈(节选):
java.lang.NoSuchMethodException: org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition.getResolvableType()
at java.lang.Class.getMethod(Class.java:1786)
at com.intellij.spring.debugger.rt...SpringBeanDefinitionLoader.getBeanClassName(SpringBeanDefinitionLoader.java:88)
at com.intellij.spring.debugger.rt...SpringBeanDefinitionLoader.getAllBeanDefinitions(SpringBeanDefinitionLoader.java:37)
at org.springframework.context.event.ContextRefreshedEvent.<init>(ContextRefreshedEvent.java:37)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896)
...
at <业务服务主类>.main(<业务服务主类>.java:...)异常发生在 Spring 上下文刷新发布 ContextRefreshedEvent 时,调用链一路可追溯到业务服务主入口。
三、结论
这不是业务代码或真实 Spring 框架的错误,而是 IntelliJ IDEA 的 Spring 调试器运行时(com.intellij.spring.debugger.rt.SpringBeanDefinitionLoader)与项目所用的 Spring 版本不兼容导致。
IDEA 升级后自带的 Spring 调试运行时按新版 Spring(5.2/5.3+) 编写,反射调用
AnnotatedGenericBeanDefinition.getResolvableType()该方法是
BeanDefinition接口的默认方法,自 Spring Framework 5.2(Spring Boot 2.2)才引入本项目使用 Spring Boot 2.1.3.RELEASE / Spring Framework 5.1.x,该方法不存在 → 反射
Class.getMethod(...)抛NoSuchMethodException
四、关键证据
getResolvableType() 是 Spring 5.2 为支持泛型/Kotlin 等场景在 BeanDefinition 接口新增的默认方法(SPR-16304)。Spring 5.1 中 AnnotatedGenericBeanDefinition 及其父类均无此方法,故反射查找必然失败。
五、影响范围
仅在 IDEA 中启动/调试应用时出现:
com.intellij.spring.debugger.rt.*运行时由 IDEA 通过 agent/classpath 注入命令行
java -jar或mvn spring-boot:run启动不会出现此异常(运行时不在 classpath)IDEA 运行时通常会 catch 该异常并打印堆栈(属于噪音刷屏),多数情况下不影响应用真正启动;若未被吞掉,则会打断
AbstractApplicationContext.refresh()导致启动失败
判断是否真正阻断启动:观察控制台是否出现
Started ... in xxx seconds。出现即表示仅刷屏噪音,可忽略。
六、处置方案
按推荐顺序:
绕开 IDEA 的 Spring 调试器启动(最稳妥)
日常调试改用命令行:
java -jar或mvn spring-boot:runIDEA 仅用于编辑代码,启动交给命令行
关闭/降级 IDEA 的 Spring Bean 调试器
Settings → Plugins,禁用或降级 Spring 相关调试插件中负责 Bean inspector 的部分
或在该 Run/Debug Configuration 的调试器选项中去掉 Spring 调试器附加
代价:丢失「Spring」工具窗口的 Bean 视图功能
仅当应用能正常启动、仅堆栈刷屏时
可直接忽略,命令行验证功能即可
不建议为此升级 Spring Boot 到 2.2+
Spring Cloud Greenwich 与 Boot 2.1 配套,升级 Boot 需同步升级 Cloud
连带影响 MyBatis-Plus、OAuth2、Activiti 等大量依赖,风险远高于收益
七、自检清单
确认项目父 POM 中
spring-boot.version仍为2.1.3.RELEASE确认堆栈调用方为
com.intellij.spring.debugger.rt.*(IDEA 调试运行时),而非业务包命令行启动复测:无
NoSuchMethodException即确认是 IDEA 调试器侧问题若应用能启动,确认控制台出现
Started ...后再判定为可忽略