Spring Integration XML过滤器迁移纯Java Config配置报错
Spring Integration Java Config 过滤器配置异常排查
场景说明
项目正在从XML/Java混合配置迁移至纯Java Config模式,暂不使用Java DSL,仅通过标注@Bean的方法实现配置。目前已完成消息通道、入站通道适配器、转换器、服务激活器的配置转换,在过滤器转换环节出现启动异常。
原XML配置中的过滤器定义如下(消息payload为java.io.File类型):
<int:filter input-channel="channelA" output-channel="channelB" ref="integrationConfiguration" method="selector"/>
承载所有Spring Integration配置的类基础结构如下:
@Configuration public class IntegrationConfiguration { // channels @Bean public MessageChannel channelA() { return new DirectChannel(); } @Bean public MessageChannel channelB() { return new DirectChannel(); } // 其他所需通道配置 // ... // 入站通道适配器 @Bean @InboundChannelAdapter(channel = "channelA") public MessageSource<File> fileReadingMessageSource() { var source = new FileReadingMessageSource(); // 源配置(与本问题无关,省略) return source; } // ... // 针对Message<File>的过滤逻辑 public boolean selector(@Header("file_name") String name, @Header("file_relativePath") String relativePath) { // 基于name和relativePath执行判断,返回true或false return true; } // 转换器 @Bean @Transformer(inputChannel = "channelB", outputChannel = "channelC") public HeaderEnricher enrichHeaders() { var expression = new SpelExpressionParser().parseExpression("..."); var headers = Map.of("additional_header", new ExpressionEvaluatingHeaderValueMessageProcessor<>(expression, String.class)); return new HeaderEnricher(headers); } // ... // 服务激活器 @Bean @ServiceActivator(inputChannel = "channelC") public FileWritingMessageHandler fileWritingMessageHandler() { var handler = new FileWritingMessageHandler( new SpelExpressionParser().parseExpression("headers.additional_header") ); // 处理器配置(与本问题无关,省略) return handler; } // ... }
错误配置尝试
最初尝试用如下配置替换XML中的过滤器定义:
@Bean @Filter(inputChannel = "channelA", outputChannel = "channelB") public boolean filter() { // 获取"file_name"和"file_relativePath"请求头 var expression1 = new SpelExpressionParser().parseExpression("headers.file_name"); var name = expression1.getValue(String.class); var expression2 = new SpelExpressionParser().parseExpression("headers.file_relativePath"); String relativePath = expression2.getValue(String.class); // 基于name和relativePath执行判断,返回true或false return true; }
报错信息
启动时抛出BeanCreationException异常,核心错误栈如下:
创建类路径资源[.../IntegrationConfiguration.class]中定义的名为'filter'的Bean失败:工厂方法实例化Bean失败;嵌套异常为org.springframework.beans.BeanInstantiationException: 实例化[boolean]类型失败:工厂方法'filter'抛出异常;嵌套异常为org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'headers' cannot be found on null
异常原因
- 被
@Bean标注的方法会在Spring容器启动阶段被直接调用,用于实例化托管到容器的Bean。上述错误配置中filter()方法返回值为基本类型boolean,Spring启动时就会执行方法内的SpEL逻辑,此时没有任何消息到达,不存在消息上下文,表达式解析时找不到headers对应的根对象,直接抛出异常。 - 配置概念混淆:
@Bean注解仅用于声明Spring框架提供的内置基础设施类型Bean,比如MessageHandler、Transformer、MessageSelector等;普通业务处理逻辑(比如这里的过滤判断方法)属于POJO方法,不需要加@Bean注解。
正确实现方案
方案1:直接复用现有POJO方法(最简洁,与原XML逻辑完全等价)
直接给已有的selector方法添加@Filter注解绑定通道即可,不需要额外包装,不要加@Bean注解:
// 注意:不要加@Bean注解,这是消息到达时才执行的业务方法 @Filter(inputChannel = "channelA", outputChannel = "channelB") public boolean selector(@Header("file_name") String name, @Header("file_relativePath") String relativePath) { // 基于name和relativePath执行判断,返回true或false return true; }
方案2:显式声明MessageSelector类型Bean
如果需要显式声明框架内置Bean类型,可以定义返回MessageSelector的@Bean方法,搭配@Filter注解使用:
@Bean @Filter(inputChannel = "channelA", outputChannel = "channelB") public MessageSelector messageSelector() { return new MessageSelector(){ @Override public boolean accept(Message<?> message){ var headers = message.getHeaders(); var name = headers.get("file_name", String.class); var relativePath = headers.get("file_relativePath", String.class); return selector(name, relativePath); } }; }
内容的提问来源于stack exchange,提问作者Marc Tarin
相关产品推荐
相关产品推荐

