Spring 5.0.0框架介紹_中文版_3.9

文章作者:Tyan
博客:noahsnail.com ?|? CSDN ?|? 簡書

3.9 基于注解的容器配置

在配置Spring時注解是否比XML更好?

基于注解配置的引入引出了一個問題——這種方式是否比基于XML的配置更好。簡短的回答是視情況而定。長一點的回答是每種方法都有它的優點和缺點,通常是由開發者決定哪一種策略更適合他們。由于注解的定義方式,注解在它們的聲明中提供了許多上下文,導致配置更簡短更簡潔。然而,XML擅長連接組件而不必接觸源代碼或重新編譯它們。一些開發者更喜歡接近源代碼,而另一些人則認為基于注解的類不再是POJOs,此外,配置變的去中心化,而且更難控制。

無論選擇是什么,Spring都能容納這兩種風格,甚至可以將它們混合在一起。值得指出的是,通過它的Java配置選項,Spring允許注解以一種非入侵的方式使用,不觸碰目標組件源碼和那些工具,所有的配置風格由Spring工具套件支持。

基于注解的配置提供了一種XML設置的可替代方式,它依賴于字節碼元數據來連接組件,而不是用尖括號聲明的方式。代替使用XML來描述bean連接,開發者通過將注解使用在相關的類,方法或字段聲明中,將配置移動到了組件類本身的內部。正如在“Example: The RequiredAnnotationBeanPostProcessor”那節提到的那樣,使用BeanPostProcessor與注解結合是擴展Spring IoC容器的的常見方法。例如,Spring 2.0引入了@Required注解來執行需要的屬性的可能性。Spring 2.5使以同樣地通用方法來驅動Spring的依賴注入變為可能。本質上來說,@Autowired提供了如3.4.5小節描述的同樣的能力。“Autowiring collaborators”但更細粒度的控制和更廣的應用性。Spring 2.5也添加對JSR-250注解的支持,例如,@PostConstruct@PreDestroy
。Spring 3.0添加了對JSR-330,包含在javax.inject包內的注解(Java的依賴注入)的支持,例如@Inject@Named。關于這些注解的細節可以在相關的小節找到。

注解注入在XML注入之前進行,因此對于通過兩種方法進行組裝的屬性后者的配置會覆蓋前者。

跟以前一樣,你可以作為單獨的bean定義來注冊它們,但也可以通過在一個基于XML的Spring配置(注入包含上下文命名空間)中包含下面的標簽來隱式的注冊它們:

<?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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

(隱式注冊的后處理器包括 AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessor和前面提到的RequiredAnnotationBeanPostProcessor。)

<context:annotation-config/>僅在定義它的同樣的應用上下文中尋找注解的beans。這意味著,如果你在一個為DispatcherServlet服務的WebApplicationContext中放置了<context:annotation-config/>,它只能在你的控制器中尋找@Autowired注解的beans,而不是在你的服務層中。更多信息請看18.2小節,“The DispatcherServlet”。

3.9.1 @Required

@Required注解應用到bean屬性的setter方法上,例子如下:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Required
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...

}

這個注解僅僅是表明受影響的bean屬性必須在配置時通過顯式的bean定義或自動組裝填充。如果受影響的bean屬性沒有填充,容器會拋出一個異常,這允許及早明確的失敗,避免NullPointerExceptions或后面出現類似的情況。仍然建議你在bean類本身加入斷言,例如,加入到初始化方法中。這樣做可以強制這些需要的引用和值,甚至是你在容器外部使用這個類的時候。

3.9.2 @Autowired

在下面的例子中JSR 330的@Inject注解可以用來代替Spring的@Autowired注解。

你可以將@Autowired注解應用到構造函數上。

public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...

}

從Spring框架4.3起,如果目標bena僅定義了一個構造函數,那么@Autowired注解的構造函數不再是必要的。如果一些構造函數是可獲得的,至少有一個必須要加上注解,以便于告訴容器使用哪一個。

正如預料的那樣,你也可以將@Autowired注解應用到“傳統的”setter方法上:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...

}

你也可以應用注解到具有任何名字和/或多個參數的方法上:

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...

}

你也可以應用@Autowired到字段上,甚至可以與構造函數混合用:

public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    private MovieCatalog movieCatalog;

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...

}

通過給帶有數組的字段或方法添加@Autowired注解,也可以從ApplicationContext中提供一組特定類型的bean:

public class MovieRecommender {

    @Autowired
    private MovieCatalog[] movieCatalogs;

    // ...

}

同樣也可以應用到具有同一類型的集合上:

public class MovieRecommender {

    private Set<MovieCatalog> movieCatalogs;

    @Autowired
    public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }

    // ...

}

如果你希望數組或列表中的項按指定順序排序,你的bean可以實現org.springframework.core.Ordered接口,或使用@Order或標準@Priority注解。

只要期望的key是String,那么類型化的Maps就可以自動組裝。Map的值將包含所有期望類型的beans,key將包含對應的bean名字:

public class MovieRecommender {

    private Map<String, MovieCatalog> movieCatalogs;

    @Autowired
    public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }

    // ...

}

默認情況下,當沒有候選beans可獲得時,自動組裝會失敗;默認的行為是將注解的方法,構造函數和字段看作指明了需要的依賴。這個行為也可以通過下面的方式去改變。

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired(required=false)
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...

}

每個類只有一個構造函數可以標記為必需的,但可以注解多個非必需的構造函數。在這種情況下,會考慮這些候選者中的每一個,Spring使用最貪婪的構造函數,即依賴最滿足的構造函數,具有最大數目的參數。

建議在@Required注解之上使用@Autowiredrequired特性。required特性表明這個屬性自動裝配是不需要的,如果這個屬性不能被自動裝配,它會被忽略。另一方面@Required是更強大的,在它強制這個屬性被任何容器支持的bean設置。如果沒有值注入,會拋出對應的異常。

你也可以對那些已知的具有可解析依賴的接口使用@AutowiredBeanFactoryApplicationContextEnvironment, ResourceLoaderApplicationEventPublisherMessageSource。這些接口和它們的擴展接口,例如ConfigurableApplicationContextResourcePatternResolver,可以自動解析,不需要特別的設置。

public class MovieRecommender {

    @Autowired
    private ApplicationContext context;

    public MovieRecommender() {
    }

    // ...

}

@Autowired@Inject@Resource@Value注解是通過Spring BeanPostProcessor實現處理,這反過來意味著你不能在你自己的BeanPostProcessorBeanFactoryPostProcessor中應用這些注解(如果有的話)。這些類型必須顯式的通過XML或使用Spring的@Bean方法來'wired up'。

3.9.3 用@Primary微調基于注解的自動裝配

因為根據類型的自動裝配可能會導致多個候選目標,所以在選擇過程中進行更多的控制經常是有必要的。一種方式通過Spring的@Primary注解來完成。當有個多個候選bean要組裝到一個單值的依賴時,@Primary表明指定的bean應該具有更高的優先級。如果確定一個'primary' bean位于候選目標中間,它將是那個自動裝配的值。

假設我們具有如下配置,將firstMovieCatalog定義為主要的MovieCatalog

@Configuration
public class MovieConfiguration {

    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { ... }

    @Bean
    public MovieCatalog secondMovieCatalog() { ... }

    // ...

}

根據這樣的配置,下面的MovieRecommender將用firstMovieCatalog進行自動裝配。

public class MovieRecommender {

    @Autowired
    private MovieCatalog movieCatalog;

    // ...

}

對應的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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="example.SimpleMovieCatalog" primary="true">
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean id="movieRecommender" class="example.MovieRecommender"/>

</beans>

3.9.4 微調基于注解且帶有限定符的自動裝配

當有多個實例需要確定一個主要的候選對象時,@Primary是一種按類型自動裝配的有效方式。當需要在選擇過程中進行更多的控制時,可以使用Spring的@Qualifier注解。為了給每個選擇一個特定的bean,你可以將限定符的值與特定的參數聯系在一起,減少類型匹配集合。在最簡單的情況下,這是一個純描述性值:

public class MovieRecommender {

    @Autowired
    @Qualifier("main")
    private MovieCatalog movieCatalog;

    // ...

}

@Qualifier注解也可以指定單個構造函數參數或方法參數:

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;
    }

    // ...

}

對應的bean定義如下。限定符值為"main"的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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://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>

對于回退匹配,bean名字被認為是默認的限定符值。因此你可以定義一個id為main的bean來代替內嵌的限定符元素,會有同樣的匹配結果。然而,盡管你可以使用這個約定根據名字引用特定的beans,但是@Autowired從根本上來講是使用可選的語義限定符來進行類型驅動注入的。這意味著限定符的值,即使回退到bean名稱,總是縮小語義類型匹配的集合;它們沒有從語義上將一個引用表達為一個唯一的bean id。好的限定符值是"main"或"EMEA"或"persistent",表達一個特定組件的性質,這個組件是獨立于bean id的,即使前面例子中像這個bean一樣的匿名bean會自動生成id。

正如前面討論的那樣,限定符也可以應用到類型結合上,例如,Set<MovieCatalog>。在這個例子中,根據聲明的限定符匹配的所有beans作為一個集合進行注入。這意味著限定符不必是唯一的;它們只是構成過濾標準。例如,你可以定義多個具有同樣限定符值"action"的MovieCatalog,所有的這些都將注入到帶有注解@Qualifier("action")Set<MovieCatalog>中。

如果你想通過名字表達注解驅動的注入,不要主要使用@Autowired,雖然在技術上能通過@Qualifier值引用一個bean名字。作為可替代產品,可以使用JSR-250 @Resource注解,它在語義上被定義為通過組件唯一的名字來識別特定的目標組件,聲明的類型與匹配過程無關。@Autowired有不同的語義:通過類型選擇候選beans,特定的String限定符值被認為只在類型選擇的候選目標中,例如,在那些標記為具有相同限定符標簽的beans中匹配一個"account"限定符。

對于那些本身定義在集合/映射或數組類型中的beans來說,@Resource是一個很好的解決方案,適用于特定的集合或通過唯一名字區分的數組bean。也就是說,自Spring 4.3起,集合/映射和數組類型中也可以通過Spring的@Autowired類型匹配算法進行匹配,只要元素類型信息在@Bean中保留,返回類型簽名或集合繼承體系。在這種情況下,限定符值可以用來在相同類型的集合中選擇,正如在前一段中概括的那樣。

自Spring 4.3起,@Autowired也考慮自引用注入,例如,引用返回當前注入的bean。注意自注入是備用;普通對其它組件的依賴關系總是優先的。在這個意義上,自引用不參與普通的候選目標選擇,因此尤其是從不是主要的;恰恰相反,它們最終總是最低的優先級。在實踐中,自引用只是作為最后的手段,例如,通過bean的事務代理調用同一實例的其它方法:在考慮抽出受影響的方法來分隔代理bean的場景中。或者,使用@Resource通過它的唯一名字可能得到一個返回當前bean的代理。

@Autowired可以應用到字段,構造函數和多參數方法上,允許通過限定符注解在參數層面上縮減候選目標。相比之下,@Resource僅支持字段和bean屬性的帶有單個參數的setter方法。因此,如果你的注入目標是一個構造函數或一個多參數的方法,堅持使用限定符。

你可以創建自己的定制限定符注解。簡單定義一個注解,在你自己的定義中提供@Qualifier注解:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {

    String value();
}

然后你可以在自動裝配的字段和參數上提供定制的限定符:

public class MovieRecommender {

    @Autowired
    @Genre("Action")
    private MovieCatalog actionCatalog;
    private MovieCatalog comedyCatalog;

    @Autowired
    public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
        this.comedyCatalog = comedyCatalog;
    }

    // ...

}

接下來,提供候選bean定義的信息。你可以添加<qualifier/>標記作為<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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://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>

在3.10小節,“類路徑掃描和管理組件”中,你將看到一個基于注解的替代方法,在XML中提供限定符元數據。特別地,看3.10.8小節,“用注解提供限定符元數據”。

在某些情況下,使用沒有值的注解就是足夠的。當注解為了通用的目的時,這是非常有用的,可以應用到跨幾個不同類型的依賴上。例如,當網絡不可用時,你可以提供一個要搜索的離線目錄。首先定義一個簡單的注解:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {

}

然后將注解添加到要自動裝配的字段或屬性上:

public class MovieRecommender {

    @Autowired
    @Offline
    private MovieCatalog offlineCatalog;

    // ...

}

現在bean定義只需要一個限定符類型:

<bean class="example.SimpleMovieCatalog">
    <qualifier type="Offline"/>
    <!-- inject any dependencies required by this bean -->
</bean>

你也可以定義接收命名屬性之外的定制限定符注解或代替簡單的值屬性。如果要注入的字段或參數指定了多個屬性值,bean定義必須匹配所有的屬性值才會被認為是一個可自動裝配的候選目標。作為一個例子,考慮下面的注解定義:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {

    String genre();

    Format format();

}

這種情況下Format是枚舉類型:

public enum Format {
    VHS, DVD, BLURAY
}

要自動裝配的字段使用定制限定符進行注解,并且包含了兩個屬性值:genreformat

public class MovieRecommender {

    @Autowired
    @MovieQualifier(format=Format.VHS, genre="Action")
    private MovieCatalog actionVhsCatalog;

    @Autowired
    @MovieQualifier(format=Format.VHS, genre="Comedy")
    private MovieCatalog comedyVhsCatalog;

    @Autowired
    @MovieQualifier(format=Format.DVD, genre="Action")
    private MovieCatalog actionDvdCatalog;

    @Autowired
    @MovieQualifier(format=Format.BLURAY, genre="Comedy")
    private MovieCatalog comedyBluRayCatalog;

    // ...

}

最后,bean定義應該包含匹配的限定符值。這個例子也證實了bean元屬性可以用來代替<qualifier/>子元素。如果可獲得<qualifier/>,它和它的屬性優先級更高,如果當前沒有限定符,自動裝配機制會將<meta/>內的值作為備用,正如下面的例子中的最后兩個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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="example.SimpleMovieCatalog">
        <qualifier type="MovieQualifier">
            <attribute key="format" value="VHS"/>
            <attribute key="genre" value="Action"/>
        </qualifier>
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <qualifier type="MovieQualifier">
            <attribute key="format" value="VHS"/>
            <attribute key="genre" value="Comedy"/>
        </qualifier>
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <meta key="format" value="DVD"/>
        <meta key="genre" value="Action"/>
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <meta key="format" value="BLURAY"/>
        <meta key="genre" value="Comedy"/>
        <!-- inject any dependencies required by this bean -->
    </bean>

</beans>

3.9.5 使用泛型作為自動裝配限定符

除了@Qualifier注解外,也可以使用Java的泛型類型作為限定符的一種暗示方式。例如,假設你有如下配置:

@Configuration
public class MyConfiguration {

    @Bean
    public StringStore stringStore() {
        return new StringStore();
    }

    @Bean
    public IntegerStore integerStore() {
        return new IntegerStore();
    }

}

假設上面的beans實現了一個泛型接口,例如,Store<String>Store<Integer>,你可以@Autowire Store接口,泛型將作為限定符使用:

@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean

@Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean

當自動裝配ListsMapsArrays時,也會應用泛型限定符:

// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@Autowired
private List<Store<Integer>> s;

3.9.6 CustomAutowireConfigurer

CustomAutowireConfigurer是一個能使你注冊自己的定制限定符注解類型的BeanFactoryPostProcessor,即使它們不使用Spring的@Qualifier注解進行注解。

<bean id="customAutowireConfigurer"
        class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
    <property name="customQualifierTypes">
        <set>
            <value>example.CustomQualifier</value>
        </set>
    </property>
</bean>

AutowireCandidateResolver通過下面的方式決定自動裝配的候選目標:

  • 每個bean定義的autowire-candidate

  • <beans/>元素可獲得的任何default-autowire-candidates模式

  • 存在@Qualifier注解和任何在CustomAutowireConfigurer中注冊的定制注解

當多個beans符合條件成為自動裝配的候選目標時,"primary" bean的決定如下:如果在候選目標中某個確定的bean中的primary特性被設為true,它將被選為目標bean。

3.9.7 @Resource

Spring也支持使用JSR-250 @Resource對字段或bean屬性setter方法進行注入。這是在Java EE 5和6中的一種通用模式,例如在JSF 1.2管理的beans或JAX-WS 2.0的端點。Spring對它管理的對象也支持這種模式。

@Resource采用名字屬性,默認情況下Spring將名字值作為要注入的bean的名字。換句話說,它遵循by-name語義,下面的例子證實了這一點:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Resource(name="myMovieFinder")
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

}

如果沒有顯式的指定名字,默認名字從字段名或setter方法中取得。在字段情況下,它采用字段名稱;在setter方法情況下,它采用bean的屬性名。因此下面的例子將名字為movieFinder的bean注入到它的setter方法中:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Resource
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

}

注解提供的名字被CommonAnnotationBeanPostProcessor感知的ApplicationContext解析為bean名字。如果你顯式地配置了Spring的SimpleJndiBeanFactory,名字會通過JNDI解析。但是建議你依賴默認行為,簡單使用Spring的JNDI查找功能保護間接查找級別。

@Resource特有的沒有顯式名字指定的情況下,類似于@Autowired@Resource會進行主要的匹配類型來代替指定名字的bean并解析已知的可解析依賴:BeanFactoryApplicationContextResourceLoaderApplicationEventPublisherMessageSource接口。

因此在下面的例子中,customerPreferenceDao字段首先查找名字為customerPreferenceDao的bean,然后回退到主要的類型為CustomerPreferenceDao的類型匹配。"context"字段會注入基于已知的可解析依賴類型ApplicationContext

public class MovieRecommender {

    @Resource
    private CustomerPreferenceDao customerPreferenceDao;

    @Resource
    private ApplicationContext context;

    public MovieRecommender() {
    }

    // ...

}

3.9.8 @PostConstruct和@PreDestroy

CommonAnnotationBeanPostProcessor不僅識別@Resource注解,而且識別JSR-250生命周期注解。在Spring 2.5引入了對這些注解的支持,也提供了在初始化回調函數和銷毀回調函數中描述的那些注解的一種可替代方式。假設CommonAnnotationBeanPostProcessor在Spring的ApplicationContext中注冊,執行這些注解的方法在生命周期的同一點被調用,作為對應的Spring生命周期接口方法或顯式聲明的回調方法。在下面的例子中,緩存會預先放置接近初始化之前,并在銷毀之前清除。

public class CachingMovieLister {

    @PostConstruct
    public void populateMovieCache() {
        // populates the movie cache upon initialization...
    }

    @PreDestroy
    public void clearMovieCache() {
        // clears the movie cache upon destruction...
    }

}

關于組合各種生命周期機制的影響的更多細節,請看“組合生命周期機制”小節。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內容