分析
首先,循环依赖是指在应用程序中,两个或更多的bean相互依赖,形成一个闭环。在Java中,这通常通过Spring框架的依赖注入来解决。
如果你在配置多个数据源时遇到循环依赖的问题,那么可能是由于你的数据源bean彼此之间存在着直接或间接的依赖关系。这可能是因为一个数据源bean的方法或构造函数中引用了另一个数据源bean,或者两个数据源bean都引用了一个共享的第三方bean,而这个第三方bean又引用了其中一个数据源bean。
解决这个问题的一种方法是使用@Lazy注解。Spring的@Lazy注解可以让Spring在需要的时候才去初始化bean,这样可以避免循环依赖的产生。
现象
Description:
The dependencies of some of the beans in the application context form a cycle:
bookInfoController (field private com.croot.portal.service.PortalBookInfoService
com.croot.portal.controller.BookInfoController.portalBookInfoService)
↓
portalBookInfoService
↓
commonService
↓
commonMapper defined in file [D:\workspace\masterportal\rims\global-module\target\classes\com\croot\global\dao\CommonMapper.class]
↓
sqlSessionFactory defined in class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]
┌─────┐
| dynamicDataSource defined in class path resource [com/croot/portal/config/DataSourceConfig.class]
↑ ↓
| datasource1 defined in class path resource [com/croot/portal/config/DataSourceConfig.class]
↑ ↓
| org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker
避免
@Configuration public class DataSourceConfig { @Bean @Lazy @ConfigurationProperties(prefix = "spring.datasource.one") public DataSource dataSourceOne() { return DataSourceBuilder.create().build(); } @Bean @Lazy @ConfigurationProperties(prefix = "spring.datasource.two") public DataSource dataSourceTwo() { return DataSourceBuilder.create().build(); } }
在这个例子中,@Lazy注解让Spring在需要dataSourceOne或dataSourceTwo的时候才去初始化它们,避免了循环依赖的产生。
但是请注意,@Lazy只能解决由于自动装配(autowiring)导致的循环依赖问题。如果你的循环依赖问题是由于其他原因导致的,比如构造函数注入,那么你可能需要寻找其他的解决方案。例如,你可能需要重新设计你的类结构,避免数据源bean之间的直接依赖。
实战
sprintboot 低版本可以使用 spring.datasource.initialize=false (默认为true) 来解决,升级到sprintboot2.1.2后就发现被启用了
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
在启动类上增加这个属性即可!