尽管使用了 @Primary,但两个同名的 bean 仍会导致 ConflictingBeanDefinitionException

fra*_*acz 4 java spring inversion-of-control spring-ioc

我有一个应用程序初始值设定项类,用于将应用程序特定数据插入数据库。

@Component("applicationInitializer")
public class ApplicationInitializer {
    @PostConstruct
    public void init(){
        // some clever code here
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个DevApplicationInitializer类用于使用开发人员计算机上的一些示例数据初始化数据库(部署生产代码时不包括此类)。

@Component("applicationInitializer")
@Primary
public class DevApplicationInitializer extends ApplicationInitializer {
    @PostConstruct
    @Override
    public void init(){
        super.init();
        // even more clever code here
    }
}
Run Code Online (Sandbox Code Playgroud)

直到我给bean命名(只有@Component注释) - 一切都工作正常 - 当DevApplicationInitializer可用时,它被实例化而不是ApplicationInitializer. 当我给它们命名时applicationInitializer,抛出异常:

org.springframework.context.annotation.ConflictingBeanDefinitionException: 
Annotation-specified bean name 'applicationInitializer' for bean class
[com.example.DevApplicationInitializer] conflicts with existing, non-compatible 
bean definition of same name and class [com.example.ApplicationInitializer]
Run Code Online (Sandbox Code Playgroud)

当bean有名称时,为什么@Primary不尊重注释?我需要他们有一个,因为我确保在其他地方初始化程序已使用@DependsOn("applicationInitializer")注释实例化。

Sot*_*lis 6

@Primary与 bean 名称无关。javadoc 指出

指示当多个候选者有资格自动装配单值依赖项时,应优先考虑某个 bean。

这仅适用于包含某些类型的两个 bean 的上下文A,其中某个类型的 bean需要注入Ban 。A带有注释的 A bean@Primary将具有优先权。

给定类型的 Bean ID/名称必须是唯一的。(对于相同的 bean 类型,具有相同名称的 Bean 定义可以相互覆盖。例如,如果您的组件扫描了带有注释的类,@Component但也@Bean为该相同类型提供了方法,就会发生这种情况。)