Spring Boot集成Jmix遇Bean循环引用问题求助
问题背景
现有两个独立应用:
- 批处理Spring Boot应用:从S3读取数据处理后写入SQL表,包路径
com.publicismedia.uniquebatchjava - Jmix主应用:需集成上述批处理应用以触发批处理
已在Jmix的build.gradle添加批处理应用依赖,并在Jmix主类配置:
@SpringBootApplication(scanBasePackages = {"com.publicismedia.uniquebatchjava"}) @EnableJmixDataRepositories(basePackages = {}) @EnableJpaRepositories(basePackages = {"com.publicismedia.uniquebatchjava.repository"})
配置意图:让Jmix加载批处理应用的Bean,通过@EnableJmixDataRepositories避免Jmix扫描所有Repository,仅用@EnableJpaRepositories扫描批处理应用的Repository,但启动时出现循环依赖错误:
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'OAuth2AuthorizationServerConfiguration': Unsatisfied dependency
expressed through field 'tokenStore'; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'sec_TokenStore' defined in class path
resource
[io/jmix/autoconfigure/securityoauth2/SecurityOAuth2AutoConfiguration$JdbcTokenStoreConfiguration.class]:
Unsatisfied dependency expressed through method 'tokenStore' parameter
0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'stellantisroiApplication': Unsatisfied
dependency expressed through field 'batchExecuter'; nested exception
is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'batchExecuter': Unsatisfied dependency
expressed through field 'batchConfigRepository'; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'batchConfigRepository' defined in
com.publicismedia.uniquebatchjava.repository.BatchConfigRepository
defined in @EnableJpaRepositories declared on
StellantisroiApplication: Cannot create inner bean '(inner
bean)#51e0629a' of type
[org.springframework.orm.jpa.SharedEntityManagerCreator] while setting
bean property 'entityManager'; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name '(inner bean)#51e0629a': Cannot resolve
reference to bean 'entityManagerFactory' while setting constructor
argument; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'jmix_Liquibase' defined in class path
resource
[io/jmix/autoconfigure/data/JmixLiquibaseAutoConfiguration.class]:
Unsatisfied dependency expressed through method 'liquibase' parameter
0; nested exception is
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'dataSource': Requested bean is
currently in creation: Is there an unresolvable circular reference?
错误根源
- 包扫描范围过大:
@SpringBootApplication(scanBasePackages)扫描了批处理应用的所有Bean,包括其内部的数据源、JPA配置类,与Jmix自身的数据源、EntityManagerFactory配置冲突。 - Repository配置未指定专属资源:
@EnableJpaRepositories未指定entityManagerFactoryRef,导致Spring尝试创建新的EntityManagerFactory,而Jmix的Liquibase初始化依赖数据源,形成循环依赖。 - 字段注入触发过早加载:批处理应用的
batchExecuter使用字段注入,在应用启动初期就触发Repository的创建,此时Jmix的核心Bean(如DataSource)尚未完全初始化。
解决方案
1. 调整Bean扫描与Repository配置
修改Jmix主类的注解,缩小扫描范围,明确指定Repository使用Jmix的EntityManagerFactory:
@SpringBootApplication // 仅扫描批处理应用中需要的业务Bean,避免扫描配置类 @ComponentScan(basePackages = { "com.publicismedia.uniquebatchjava.service", "com.publicismedia.uniquebatchjava.batch" }) // 保留Jmix默认的Repository扫描逻辑,不要设为空 @EnableJmixDataRepositories // 指定批处理Repository使用Jmix的核心JPA资源 @EnableJpaRepositories( basePackages = {"com.publicismedia.uniquebatchjava.repository"}, entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager" ) public class StellantisroiApplication { // ... }
2. 排除批处理应用的冲突自动配置
在Jmix的application.yml中,排除批处理应用带来的重复自动配置:
spring: autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
3. 修复循环依赖
将批处理应用中batchExecuter的字段注入改为构造注入,并添加@Lazy延迟初始化:
@Component public class BatchExecuter { private final BatchConfigRepository batchConfigRepository; // 构造注入+延迟加载,避免启动时过早触发Repository初始化 public BatchExecuter(@Lazy BatchConfigRepository batchConfigRepository) { this.batchConfigRepository = batchConfigRepository; } // ...批处理逻辑 }
通用Spring Boot应用集成方法(主应用+依赖应用)
当需要将com.package2.*的Spring Boot应用集成到com.package1.*主应用时,遵循以下步骤:
- 缩小扫描范围:不要直接扫描依赖应用的根包,仅扫描需要的业务Bean(Service、Component等),排除配置类、自动配置类。
- 共享核心资源:让依赖应用使用主应用的DataSource、EntityManagerFactory、TransactionManager,通过
@EnableJpaRepositories的entityManagerFactoryRef、transactionManagerRef指定。 - 排除冲突自动配置:在主应用中排除依赖应用的DataSource、JPA等自动配置类,避免重复创建核心Bean。
- 处理循环依赖:优先使用构造注入,必要时添加
@Lazy延迟初始化Bean,避免启动时过早触发依赖加载。 - 显式导入配置:如果依赖应用有必要的配置类,使用
@Import显式导入,而非包扫描。
内容的提问来源于stack exchange,提问作者kiranouseph

