Spring 容器中的 Bean 之間會有很多依賴關系零聚,在注入依賴的時候,容器需要明確知道注入的是哪一個 Bean些侍。
一隶症、類型注入沖突
Spring 容器中的 Bean 依賴可以通過名稱注入,或者類型注入岗宣。
通過名稱注入
名稱注入會指定一個明確的 Bean 名稱蚂会,容器不允許注冊相同名稱的 Bean,所以不會有任何問題耗式。
通過類型注入
通過類型注入的時候胁住,有時會因為多個 Bean 的類型相同而產(chǎn)生沖突。例如:
- 同一類型注冊多個不同名稱的 Bean
- 抽象類型注冊多個不同實現(xiàn)類的 Bean
這種情況下纽什,容器不知道該注入哪個會拋出 NoUniqueBeanDefinitionException
異常措嵌。
二、解決沖突
假設在項目中定義一個 BeanService
接口芦缰,基于該接口有三個實現(xiàn)類 OneServiceImpl
企巢、TwoServiceImpl
和 ThreeServiceImpl
,三個實現(xiàn)類都由 Spring 容器管理让蕾。
在項目中通過 BeanService
接口的類型注入浪规,會產(chǎn)生沖突拋出異常。
// BeanService的三個實現(xiàn)類注冊Bean
@Configuration
public class AppConfig {
@Bean
public BeanService oneServiceImpl() {
return new OneServiceImpl();
}
@Bean
public BeanService twoServiceImpl() {
return new TwoServiceImpl();
}
@Bean
public BeanService threeServiceImpl() {
return new ThreeServiceImpl();
}
}
// 通過接口的類型注入會拋出異常
public class ServiceTest {
@Autowired
private BeanService beanService;
}
1. 注入主要的
注冊 Bean 的時候探孝,使用 @Primary
指定一個 Bean 為主要的笋婿,存在沖突時默認選擇主要的 Bean。
@Configuration
public class AppConfig {
@Bean
@Primary
public BeanService oneServiceImpl() {
return new OneServiceImpl();
}
// ......
}
@Primary
注解也可和 @Component
等注解一起使用顿颅。
2. 注入指定的
注入 Bean 的時候缸濒,使用 @Qualifier
指定具體 Bean 的名稱,通過名稱注入解決沖突。
public class ServiceTest {
@Autowired
@Qualifier("oneServiceImpl")
private BeanService beanService;
// ......
}
也可以直接通過字段名稱來指定具體 Bean 的名稱庇配,來解決沖突斩跌。
public class ServiceTest {
@Autowired
private BeanService oneServiceImpl;
// ......
}
上面兩種方法同樣適用于構造器注入和 Setter 方法注入。
三捞慌、注入多個 Bean
在實際應用中耀鸦,如果需要注入符合類型的所有 Bean,可以使用集合類型來注入啸澡。
集合類型的注入同樣適用于字段注入袖订、構造器注入和 Setter 方法注入。
1. 注入集合
通過數(shù)組來注入一種類型的所有 Bean嗅虏。
public class ServiceTest {
@Autowired
private BeanService[] beanServiceArr;
// ......
}
通過 List
來注入一種類型的所有 Bean洛姑。
public class ServiceTest {
@Autowired
private List<BeanService> beanServiceList;
// ......
}
通過 Set
來注入一種類型的所有 Bean。
public class ServiceTest {
@Autowired
private Set<BeanService> beanServiceSet;
// ......
}
2. 注入 Map
通過 Map
來注入一種類型的所有 Bean旋恼,Key 的類型固定為 String
吏口。
Key 存儲 Bean 的名稱,Value 存儲 Bean 的實例冰更。
public class ServiceTest {
@Autowired
private Map<String, BeanService> beanServiceMap;
// ......
}
3. Bean 的順序
注冊 Bean 的時候可以使用 @Order
注解來指定 Bean 的權重(或順序)产徊。
在使用有序集合(數(shù)組或 List
)注入的時候,會根據(jù)權重來排序蜀细。
@Configuration
public class AppConfig {
@Bean
@Order(1)
public BeanService oneServiceImpl() {
return new OneServiceImpl();
}
@Bean
@Order(3)
public BeanService twoServiceImpl() {
return new TwoServiceImpl();
}
@Bean
@Order(2)
public BeanService threeServiceImpl() {
return new ThreeServiceImpl();
}
}
上面配置類注冊的 Bean 使用數(shù)組或 List
注入時舟铜,注入集合類型的元素順序為:
0 = {OneServiceImpl@1522}
1 = {ThreeServiceImpl@1527}
2 = {TwoServiceImpl@1528}
@Order
注解也可和 @Component
等注解一起使用。
四奠衔、附錄
1. 常用注解
注解 | 描述 |
---|---|
@Primary |
指定主要的 Bean谆刨,存在注入沖突時默認注入的 Bean |
@Qualifier |
指定注入 Bean 的名稱 |
@Order |
指定注冊同類型的 Bean 的權重(或順序),值越小归斤,權重越大痊夭。 |
2. 示例代碼
Gitee 倉庫:https://gitee.com/code_artist/spring
項目模塊:spring-ioc
示例路徑:cn.codeartist.spring.bean.multi
最新文章關注 CodeArtist 碼匠公眾號。