Spring Boot从2.1.9升级到2.2.1后出现ClassCastException(Spring Integration)
这个ClassCastException其实不是Spring Integration的Bug,而是Spring Boot DevTools的类加载器机制和Spring Integration 5.2.x早期版本的一个小兼容性问题,而且因为异常被框架捕获并仅以DEBUG级别记录,所以完全不影响应用正常运行。
为什么会触发这个异常?
Spring Boot DevTools为了实现热重启,用了双类加载器的设计:RestartClassLoader负责加载你的应用代码(比如你的ConfirmationMailTransformer),而系统类加载器加载Spring的核心类(比如org.springframework.aop.framework.Advised)。
在Spring Integration 5.2.1的MessagingMethodInvokerHelper.getTargetClass方法里,框架会尝试判断目标Bean是否是Spring的代理对象(即是否实现Advised接口),但你的类和Advised类来自不同的类加载器,JVM会认为这是两个完全不同的类型,于是抛出了ClassCastException。
不过放心,框架代码里已经捕获了这个异常,捕获后会直接返回原类的类型,继续执行后续逻辑,所以应用能正常启动运行,只是会输出这条DEBUG日志。
解决办法
你可以从以下几个方案里选一个:
升级到修复后的版本
Spring Integration在5.2.2版本中修复了这个类加载器兼容问题,对应的Spring Boot版本是2.2.2.RELEASE及以上。直接升级Spring Boot版本,这条日志就会消失。调整DevTools的类加载范围
在src/main/resources/META-INF/spring-devtools.properties中添加配置,把你的应用包加入restart的白名单,让它由系统类加载器加载:
spring.devtools.restart.additional-paths=com.demo
或者直接排除你的应用包,不让RestartClassLoader加载:
spring.devtools.restart.exclude=com/demo/**
- 临时禁用DevTools的热重启功能
如果开发中不需要热重启,可以在application.properties里关闭这个功能:
spring.devtools.restart.enabled=false
额外说明
你的ConfirmationMailTransformer代码和Spring Integration的XML配置都是完全正确的,不需要做任何修改。这个问题只是日志层面的小干扰,不会影响业务逻辑的执行。
内容的提问来源于stack exchange,提问作者Jesper

