Spring Boot升级至Java11后SPel报错EL1005E无法找到指定类型
问题触发根因
这个问题是JDK版本升级后类加载器变化和Spring Integration SpEL表达式上下文初始化逻辑共同导致的:
- Java 9及以上版本引入了JPMS模块系统,类加载的层级和权限规则和JDK8有明显差异
- Spring Boot 2.2.x版本配套的Spring Integration 5.2.x在初始化默认
IntegrationEvaluationContext的StandardTypeLocator时,使用的是框架自身的类加载器,无法识别应用自定义业务包下的类,因此SpEL表达式中用T(com.foo.integration.FlowHeaders)引用类的时候会抛出类型找不到的异常 - 你自定义的
CustomStandardTypeLocator无参构造默认使用ClassUtils.getDefaultClassLoader()(也就是应用的上下文类加载器),可以正常加载业务类,因此临时方案可以生效
更规范的解决方案
方案1(最推荐):使用函数式路由替代字符串SpEL表达式
直接在路由方法中传入Lambda表达式处理消息,从根源避免SpEL类型查找的问题,代码可读性和可维护性也更高:
.route(Message.class, message -> message.getHeaders().get(FlowHeaders.FEED, Feed.class).getProcessingMode(), m -> m.subFlowMapping(Feed.ProcessingMode.stream, this.streamFlow(sinkStreamProcessingHandler)) .subFlowMapping(Feed.ProcessingMode.batch, this.batchFlow(sinkBatchProcessingHandler, props)) .subFlowMapping(Feed.ProcessingMode.group, ...) )
方案2:显式配置SpEL类型定位器的类加载器
如果必须保留字符串SpEL的写法,不需要自定义TypeLocator子类,直接给默认的类型定位器传入应用类加载器即可:
@Bean(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME) public IntegrationEvaluationContextFactoryBean evaluationContextFactoryBean(){ IntegrationEvaluationContextFactoryBean factoryBean = new IntegrationEvaluationContextFactoryBean(); factoryBean.setTypeLocator(new StandardTypeLocator(ClassUtils.getDefaultClassLoader())); return factoryBean; }
内容的提问来源于stack exchange,提问作者Gaurav Rawat
相关产品推荐
相关产品推荐

