SpringFramework Core(七)

@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>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容