@Primary
由于按類型自動(dòng)裝配可能會(huì)導(dǎo)致多個(gè)候選對(duì)象,因此通常有必要更好地控制選擇過(guò)程。一種實(shí)現(xiàn)此目的的方法是使用Spring的 @Primary注釋。
@Primary指示當(dāng)多個(gè)bean是要自動(dòng)裝配到單值依賴項(xiàng)的候選對(duì)象時(shí),應(yīng)給予特定bean優(yōu)先權(quán)。如果候選對(duì)象中僅存在一個(gè)主bean,則它將成為自動(dòng)裝配的值。
考慮以下定義firstMovieCatalog為主要配置的配置MovieCatalog:
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
使用前面的配置,以下內(nèi)容MovieRecommender將自動(dòng)連接到 firstMovieCatalog:
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
限定符 @Qualifier
當(dāng)您需要對(duì)選擇過(guò)程進(jìn)行更多控制時(shí),可以使用Spring的@Qualifier注釋。您可以將限定符值與特定的參數(shù)相關(guān)聯(lián),從而縮小類型匹配的范圍,以便為每個(gè)參數(shù)選擇特定的bean。在最簡(jiǎn)單的情況下,這可以是簡(jiǎn)單的描述性值,如以下示例所示:
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
您還可以@Qualifier在各個(gè)構(gòu)造函數(shù)參數(shù)或方法參數(shù)上指定注釋,如以下示例所示:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
以下示例顯示了相應(yīng)的bean定義。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier value="main"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
對(duì)于后備匹配,bean名稱被認(rèn)為是默認(rèn)的限定符值。因此,可以使用idof main而不是嵌套的限定符元素來(lái)定義bean ,從而得到相同的匹配結(jié)果。但是,盡管您可以使用此約定按名稱引用特定的bean,但從@Autowired根本上講,它是帶有可選語(yǔ)義限定符的類型驅(qū)動(dòng)的注入。這意味著,即使帶有Bean名稱后退的限定符值,在類型匹配集中也始終具有狹窄的語(yǔ)義。它們沒(méi)有在語(yǔ)義上表示對(duì)唯一bean的引用id。好的限定符值是main 或EMEA或persistent,表示獨(dú)立于Bean的特定組件的特征id,如果是匿名bean定義(例如前面的示例中的定義),則可以自動(dòng)生成。
限定詞也適用于類型化的集合,如前所述(例如,) Set<MovieCatalog>。在這種情況下,根據(jù)聲明的限定符,將所有匹配的bean作為集合注入。這意味著限定詞不必是唯一的。相反,它們構(gòu)成了過(guò)濾標(biāo)準(zhǔn)。例如,您可以定義MovieCatalog具有相同限定符值“ action”的多個(gè)bean,所有這些都將注入到帶Set<MovieCatalog>注釋的中@Qualifier("action")。
在類型匹配的候選對(duì)象中,讓限定符值針對(duì)目標(biāo)Bean名稱進(jìn)行選擇,不需要@Qualifier在注入點(diǎn)處進(jìn)行注釋。如果沒(méi)有其他解析度指示符(例如限定詞或主標(biāo)記),則對(duì)于非唯一依賴性情況,Spring將注入點(diǎn)名稱(即字段名稱或參數(shù)名稱)與目標(biāo)Bean名稱進(jìn)行匹配,然后選擇同名候選人(如果有)。
您可以創(chuàng)建自己的自定義限定符注釋。為此,請(qǐng)定義一個(gè)注釋并@Qualifier在您的定義中提供該注釋,如以下示例所示:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
然后,您可以在自動(dòng)連接的字段和參數(shù)上提供自定義限定符,如以下示例所示:
public class MovieRecommender {
@Autowired
@Genre("Action")
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
}
// ...
}
接下來(lái),您可以提供有關(guān)候選bean定義的信息。您可以將<qualifier/>標(biāo)簽添加為 標(biāo)簽的子元素,<bean/>然后指定type和 value以匹配您的自定義限定符注釋。該類型與注釋的標(biāo)準(zhǔn)類名匹配。另外,為方便起見,如果不存在名稱沖突的風(fēng)險(xiǎn),則可以使用簡(jiǎn)短的類名。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="example.Genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>