当有两个用@Qualifier 定义的候选项时,Spring 如何决定注入哪个bean?
How does Spring decide which bean to inject when there is two candidates defined with @Qualifier?
假设我有两个这样定义的bean:
@Configuration
public class ConfigurationA {
@Bean
@Qualifier("restTemplateA")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
@Configuration
public class ConfigurationB {
@Bean
@Qualifier("restTemplateB")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
当我在不提供@Qualifier 的情况下自动装配restTemplate 时,将注入哪个bean?怎么决定的?
@Service
public class someClass {
@Autowired
private RestTemplate restTemplate;
}
注意:我测试的时候注入了其中一个bean。它没有导致任何异常。
注2:我知道我可以使用@Qualifier 来注入我想要的bean,或者我可以使用@Primary 来避免歧义。但是我只是想明白为什么它对Spring有效。
注3:当我将classConfigurationB中的方法名改成restTemplateB时,注入了ConfigurationA中定义的bean。同样,它没有导致任何异常。
我在 Spring 引导版本 1.4.4
中试过这个
实际上,您不能同时拥有这两种配置 class,因为这样会导致 bean 名称冲突。要解决此问题,请重命名方法名称:
@Bean
@Qualifier("restTemplateB")
public RestTemplate restTemplateB() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
这样,将创建两个RestTemplate
,分别使用restTemplate
和restTemplateB
名称,第一个将在服务class中注入。
我想你会发现,如果你 运行 你的应用程序,它会记录一个错误,如 requried a single bean but 2 were found
。
然而,您可以做的是使用 @Qualifier 在您需要注入并命名您的 bean 定义的地方消除歧义,即对于您的示例。
@Configuration
public class Configuration {
@Bean(name="restTemplateA")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
@Bean(name="restTemplateB")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
然后当你开始注入和使用模板时
@Service
public class someClass {
@Autowired
@Qualifer("restTemplateA")
private RestTemplate restTemplate;
}
但是,您也可以使用 @Primary
将其中一个模板标记为主要模板,然后该 bean 将在您不符合自动装配条件的每个地方使用。
@Bean(name="restTemplateA")
@Primary
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
案例 1: 配置中的相同方法(bean)名称 类。
@Configuration
public class ConfigurationA {
@Bean
@Qualifier("restTemplateA")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
@Configuration
public class ConfigurationB {
@Bean
@Qualifier("restTemplateB")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
结果:注入ConfigrationB中的restTemplate。 ConfigurationA 中的 restTemplate 被 ConfigurationB 中的 restTemplate 覆盖,如日志中所示:
o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition
for bean 'restTemplate' with a different definition: replacing ...
重要说明:从 spring 引导版本 2.1 开始,Bean 覆盖默认禁用(您可以查看此 link)
案例2:将ConfigurationB中的方法名更改为restTemplateB。
@Configuration
public class ConfigurationA {
@Bean
@Qualifier("restTemplateA")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
@Configuration
public class ConfigurationB {
@Bean
@Qualifier("restTemplateB")
public RestTemplate restTemplateB() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
结果: ConfigurationA 和 ConfigurationB 中的两个 bean 都已创建。 ConfigurationA 中的 Bean 被注入。因为如果按类型自动装配找不到单个匹配的 bean,将使用 bean 名称。检查 了解更多信息
假设我有两个这样定义的bean:
@Configuration
public class ConfigurationA {
@Bean
@Qualifier("restTemplateA")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
@Configuration
public class ConfigurationB {
@Bean
@Qualifier("restTemplateB")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
当我在不提供@Qualifier 的情况下自动装配restTemplate 时,将注入哪个bean?怎么决定的?
@Service
public class someClass {
@Autowired
private RestTemplate restTemplate;
}
注意:我测试的时候注入了其中一个bean。它没有导致任何异常。
注2:我知道我可以使用@Qualifier 来注入我想要的bean,或者我可以使用@Primary 来避免歧义。但是我只是想明白为什么它对Spring有效。
注3:当我将classConfigurationB中的方法名改成restTemplateB时,注入了ConfigurationA中定义的bean。同样,它没有导致任何异常。
我在 Spring 引导版本 1.4.4
中试过这个实际上,您不能同时拥有这两种配置 class,因为这样会导致 bean 名称冲突。要解决此问题,请重命名方法名称:
@Bean
@Qualifier("restTemplateB")
public RestTemplate restTemplateB() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
这样,将创建两个RestTemplate
,分别使用restTemplate
和restTemplateB
名称,第一个将在服务class中注入。
我想你会发现,如果你 运行 你的应用程序,它会记录一个错误,如 requried a single bean but 2 were found
。
然而,您可以做的是使用 @Qualifier 在您需要注入并命名您的 bean 定义的地方消除歧义,即对于您的示例。
@Configuration
public class Configuration {
@Bean(name="restTemplateA")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
@Bean(name="restTemplateB")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
然后当你开始注入和使用模板时
@Service
public class someClass {
@Autowired
@Qualifer("restTemplateA")
private RestTemplate restTemplate;
}
但是,您也可以使用 @Primary
将其中一个模板标记为主要模板,然后该 bean 将在您不符合自动装配条件的每个地方使用。
@Bean(name="restTemplateA")
@Primary
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
案例 1: 配置中的相同方法(bean)名称 类。
@Configuration
public class ConfigurationA {
@Bean
@Qualifier("restTemplateA")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
@Configuration
public class ConfigurationB {
@Bean
@Qualifier("restTemplateB")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
结果:注入ConfigrationB中的restTemplate。 ConfigurationA 中的 restTemplate 被 ConfigurationB 中的 restTemplate 覆盖,如日志中所示:
o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'restTemplate' with a different definition: replacing ...
重要说明:从 spring 引导版本 2.1 开始,Bean 覆盖默认禁用(您可以查看此 link)
案例2:将ConfigurationB中的方法名更改为restTemplateB。
@Configuration
public class ConfigurationA {
@Bean
@Qualifier("restTemplateA")
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
@Configuration
public class ConfigurationB {
@Bean
@Qualifier("restTemplateB")
public RestTemplate restTemplateB() {
RestTemplate restTemplate = new RestTemplate();
//setting some restTemplate properties
return restTemplate;
}
}
结果: ConfigurationA 和 ConfigurationB 中的两个 bean 都已创建。 ConfigurationA 中的 Bean 被注入。因为如果按类型自动装配找不到单个匹配的 bean,将使用 bean 名称。检查