为什么Spring Boot会创建相同类型的bean,而不管@Primary注释是什么?

时间:2017-06-30 13:10:24

标签: java spring spring-boot

我有一个Spring Configuration类,如下所示:

@Configuration
public class MyDependencyConfig {

@Bean
@Primary
public MyDependency getMyDependency(){
    System.out.println("getMyDependency");
    return Mockito.mock(MyDependency.class);
}

@Bean
public MyDependency getMyDependency2(){
    System.out.println("getMyDependency2");
    return Mockito.mock(MyDependency.class);
}
}

我的代码中有其他地方:

@Autowired
MyDependency foo

为什么在应用程序上下文启动时,我的控制台打印

  

getMyDependency

     

getMyDependency2

何时只使用来自getMyDependency()的bean?我正在使用spring boot-1.5.1.RELEASE

谢天谢地, 杰森

1 个答案:

答案 0 :(得分:6)

Spring配置在Spring上下文启动时实例化并加载Spring容器中所有已声明和必需的bean。

因此,即使您不使用配置中定义的所有bean,也会调用配置中注释为@Bean的方法。

The @Primary annotation还有另一个目标。

  

它表示在多个bean时应该优先考虑bean   候选人有资格自动使用单值依赖。如果   在候选人中确实存在一个“主要”bean,它将是   自动装配价值。

当你有多个候选bean时,这只是一种不系统地指定@Qualifier注释的方法。

例如,在您的情况下,将两个bean中的一个指定为primary

@Bean
@Primary
public MyDependency getMyDependency(){
    System.out.println("getMyDependency");
    return Mockito.mock(MyDependency.class);
}

您无需指定限定符"getMyDependency"来注入指定为primary的限定符:

@Autowired
@Qualifier("getMyDependency")
MyDependency foo;

你可以直接这样做:

@Autowired
MyDependency foo;

对于第二个未指定为@Primary的bean:

@Bean
public MyDependency getMyDependency2(){
    System.out.println("getMyDependency2");
    return Mockito.mock(MyDependency.class);
}

当您想要注射时,您必须指定@Qualifier以清除歧义:

@Autowired
@Qualifier("getMyDependency2")
MyDependency foo;

不建议以懒惰的方式加载bean,因为它会延迟配置错误的捕获。所以,默认情况下是急切的。

您在评论中提供的link中有更多详细信息。
现在,如果要阻止此默认行为并为bean定义延迟初始化,您也可以在bean的lazy注释中指定String @Scope值:

@Bean 
@Scope("lazy")
public MyDependency getMyDependency(){
  ...
}

或者更好,您可以使用@Lazy注释来注释bean声明或所有配置(如果您希望所有bean都是延迟初始化的)。

对于特定的bean:

@Bean 
@Lazy
public MyDependency getMyDependency(){
   ...
}

对于配置的所有bean:

@Lazy
@Configuration
public class MyDependencyConfig {
   ...
}