Spring 启动 - 单个 @Configuration @import 可以工作,但多个不能,为什么?
Spring boot - A single @Configuration @import will work but multiple will not, why?
在 Spring 引导项目中,我有一个 RestController 包含:
@Autowired
private ProactiveDbManager proactiveDbManager;
@Autowired
private CoreDbManager coreDbManager;
这 2 个数据库管理器位于另一个 Spring 引导模块中,因此我使用配置 class:
导入它们
@Configuration
@PropertySource("classpath:application.properties")
@Import({ProactiveDbCommonsConfig.class})
public class ProactiveDbConfig {
}
和:
@Configuration
@PropertySource("classpath:application.properties")
@Import({CoreDbCommonsConfig.class})
public class CoreDbConfig {
}
ProactiveDbCommonsConfig
和CoreDbCommonsConfig
也是配置。
ProactiveDbCommonsConfig
:
@Configuration
public class ProactiveDbCommonsConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ProactiveDbCommonsConfig.class);
private ProactiveDbManager proactiveDbManager;
@Bean
public MasterHandler masterHandler() {
return new MasterHandler(true);
}
@Bean
public ProactiveDbManager dBManager(MasterHandler masterHandler) {
List<String> dbConnectionStrings = masterHandler.getDbConnectionStringsJsonsList(DbConsts.DEFAULT_DATA_CENTER);
LOGGER.debug("DB manager created.");
proactiveDbManager = new ProactiveDbManager(dbConnectionStrings);
return proactiveDbManager;
}
@Override
protected void finalize() {
try {
closeDbConnection();
} catch (Exception ignored) {
}
}
@PreDestroy
public void closeDbConnection() throws Exception {
if (this.proactiveDbManager != null) {
this.proactiveDbManager.disconnect();
this.proactiveDbManager = null;
}
}
}
我的问题是,如果我删除控制器中的 1 个自动装配并删除其配置(即 ProactiveDbConfig
),那么它就可以工作了。他们两个都是单独工作,但不是一起工作。
我得到的错误是:
Field coreDbManager in x.y.z.controllers.h required a bean of type 'x.y.a.db.managers.CoreDbManager' that could not be found.
堆栈跟踪:
15:56:14.609 [main] DEBUG o.s.b.d.LoggingFailureAnalysisReporter - Application failed to start due to an exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'x.y.db.managers.CoreDbManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at x.y.app.MyApp.main(MyApp.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:66)
15:56:14.609 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter -
当使用 @Configuration
类 且未在 @Bean(name = "<your-name-here>")
中明确定义 bean 名称时,方法名称将用作 bean 的名称。
如果您导入多个包含同名 bean 的配置文件,一个将覆盖另一个。 Spring Boot 的较新版本通过禁用覆盖(默认情况下启用)来防止这种情况,这将导致启动时出现异常。
对于您的解决方案,重命名方法或向 @Bean
注释添加显式名称。
在 Spring 引导项目中,我有一个 RestController 包含:
@Autowired
private ProactiveDbManager proactiveDbManager;
@Autowired
private CoreDbManager coreDbManager;
这 2 个数据库管理器位于另一个 Spring 引导模块中,因此我使用配置 class:
导入它们@Configuration
@PropertySource("classpath:application.properties")
@Import({ProactiveDbCommonsConfig.class})
public class ProactiveDbConfig {
}
和:
@Configuration
@PropertySource("classpath:application.properties")
@Import({CoreDbCommonsConfig.class})
public class CoreDbConfig {
}
ProactiveDbCommonsConfig
和CoreDbCommonsConfig
也是配置。
ProactiveDbCommonsConfig
:
@Configuration
public class ProactiveDbCommonsConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ProactiveDbCommonsConfig.class);
private ProactiveDbManager proactiveDbManager;
@Bean
public MasterHandler masterHandler() {
return new MasterHandler(true);
}
@Bean
public ProactiveDbManager dBManager(MasterHandler masterHandler) {
List<String> dbConnectionStrings = masterHandler.getDbConnectionStringsJsonsList(DbConsts.DEFAULT_DATA_CENTER);
LOGGER.debug("DB manager created.");
proactiveDbManager = new ProactiveDbManager(dbConnectionStrings);
return proactiveDbManager;
}
@Override
protected void finalize() {
try {
closeDbConnection();
} catch (Exception ignored) {
}
}
@PreDestroy
public void closeDbConnection() throws Exception {
if (this.proactiveDbManager != null) {
this.proactiveDbManager.disconnect();
this.proactiveDbManager = null;
}
}
}
我的问题是,如果我删除控制器中的 1 个自动装配并删除其配置(即 ProactiveDbConfig
),那么它就可以工作了。他们两个都是单独工作,但不是一起工作。
我得到的错误是:
Field coreDbManager in x.y.z.controllers.h required a bean of type 'x.y.a.db.managers.CoreDbManager' that could not be found.
堆栈跟踪:
15:56:14.609 [main] DEBUG o.s.b.d.LoggingFailureAnalysisReporter - Application failed to start due to an exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'x.y.db.managers.CoreDbManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at x.y.app.MyApp.main(MyApp.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:66)
15:56:14.609 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter -
当使用 @Configuration
类 且未在 @Bean(name = "<your-name-here>")
中明确定义 bean 名称时,方法名称将用作 bean 的名称。
如果您导入多个包含同名 bean 的配置文件,一个将覆盖另一个。 Spring Boot 的较新版本通过禁用覆盖(默认情况下启用)来防止这种情况,这将导致启动时出现异常。
对于您的解决方案,重命名方法或向 @Bean
注释添加显式名称。