如何解决Spring Integration中`java.lang.RuntimeException: No beanFactory`警告
问题根源及解决方案
问题原因
出现No beanFactory警告的核心原因是:你手动创建的SftpInboundFileSynchronizer和SftpInboundFileSynchronizingMessageSource没有被Spring容器托管,导致它们的父类AbstractExpressionEvaluator无法自动获取BeanFactory实例,而该实例是初始化表达式上下文的必要依赖。
同时,你在createFileSynchronizer方法中直接调用sessionFactory()(@Bean注解的方法),这会绕过Spring的Bean管理机制,每次调用都会创建新的CachingSessionFactory实例,既浪费资源,也进一步导致同步器无法关联到正确的容器上下文。
修复方案
将SftpInboundFileSynchronizer和MessageSource都声明为Spring Bean,通过依赖注入获取容器中的单例SessionFactory,让Spring负责管理它们的生命周期和依赖注入。
修改后的完整代码
@Configuration public class SftpIntegrationConfig { @Bean public SessionFactory<SftpClient.DirEntry> sessionFactory() { return getDirEntrySessionFactory(); } SessionFactory<SftpClient.DirEntry> getDirEntrySessionFactory() { DefaultSftpSessionFactory sessionFactory = new DefaultSftpSessionFactory(); sessionFactory.setHost("localhost"); sessionFactory.setPort(22); sessionFactory.setUser("test"); sessionFactory.setPassword("test"); sessionFactory.setAllowUnknownKeys(true); sessionFactory.isSharedSession(); return new CachingSessionFactory<>(sessionFactory); } // 为每个远程目录创建独立的同步器Bean @Bean public SftpInboundFileSynchronizer fileSynchronizer987597720(SessionFactory<SftpClient.DirEntry> sessionFactory) { SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sessionFactory); fileSynchronizer.setDeleteRemoteFiles(true); fileSynchronizer.setRemoteDirectory("data/987597720"); fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter("*.xml")); return fileSynchronizer; } @Bean public SftpInboundFileSynchronizer fileSynchronizer999999999(SessionFactory<SftpClient.DirEntry> sessionFactory) { SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sessionFactory); fileSynchronizer.setDeleteRemoteFiles(true); fileSynchronizer.setRemoteDirectory("data/999999999"); fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter("*.xml")); return fileSynchronizer; } // 通过依赖注入获取同步器,创建MessageSource Bean @Bean public MessageSource<File> sftpMessageSource987597720(SftpInboundFileSynchronizer fileSynchronizer987597720) { SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(fileSynchronizer987597720); source.setLocalDirectory(new File("C:\\Users\\jb\\src\\ihr-robot-integration\\target_folder")); source.setAutoCreateLocalDirectory(true); source.setLocalFilter(new AcceptOnceFileListFilter<File>()); source.setMaxFetchSize(1); return source; } @Bean public MessageSource<File> sftpMessageSource999999999(SftpInboundFileSynchronizer fileSynchronizer999999999) { SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(fileSynchronizer999999999); source.setLocalDirectory(new File("C:\\Users\\jb\\src\\ihr-robot-integration\\target_folder")); source.setAutoCreateLocalDirectory(true); source.setLocalFilter(new AcceptOnceFileListFilter<File>()); source.setMaxFetchSize(1); return source; } @Bean public IntegrationFlow sftpFlow987597720() { return IntegrationFlow.from(sftpMessageSource987597720(), c -> c.poller(Pollers.fixedDelay(10000))) .channel("sftpChannel") .get(); } @Bean public IntegrationFlow sftpFlow999999999() { return IntegrationFlow.from(sftpMessageSource999999999(), c -> c.poller(Pollers.fixedDelay(10000))) .channel("sftpChannel") .get(); } @Bean public IntegrationFlow mergedSftpFlow(){ return IntegrationFlow.from("sftpChannel") .channel("processChannel") .handle(message -> System.out.println(String.format("Processing new incoming file named: %s", message.getHeaders().get("file_name")))) .get(); } }
关键修改点
- 将
SftpInboundFileSynchronizer拆分为两个独立的Bean,通过方法参数注入容器中的单例SessionFactory。 MessageSourceBean同样通过依赖注入获取对应的同步器,确保所有组件都被Spring容器管理。- 避免直接调用@Bean方法创建实例,改用依赖注入获取容器中的单例Bean,保证上下文一致性。
内容的提问来源于stack exchange,提问作者jcb
相关产品推荐
相关产品推荐

