spring @Primary @Autowired @Qualifier 注解的使用戶和區別

@Autowired

在使用spring開發過程中,我們基本上都是使用 @Autowired 這個注解,用來注入已有的 bean。當 spring 中管理兩個類型一樣的 bean 時,再進行注入時會報錯:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.pb.spring.Spring5AutowiredQualifierApplicationTests': Unsatisfied dependency expressed through field 'user3'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.pb.spring.domain.User' available: expected single matching bean but found 2: user1,getUser2
 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)

required 屬性

@Autowired(required=true):當使用 @Autowired 注解的時候,其實默認就是@Autowired(required=true),表示注入的時候,該 bean 必須存在,否則就會注入失敗。

@Autowired(required=false):表示忽略當前要注入的 bean,如果有直接注入,沒有跳過,不會報錯。

@Primary

看下面代碼,@Primary 表示當遇到系統中有兩個User類型時,優先使用 @Primary 注解的這個進行注入。

import com.pb.spring.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
 
@Configuration
public class UserConfig {
 
    @Bean(name = "user1")
    public User getUser1(){
        return new User("theodore",25);
    }
 
    @Primary
    @Bean(name = "user2")
    public User user2(){
        return new User("james",25);
    }
}
import com.pb.spring.domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
 
@RunWith(SpringRunner.class)
@SpringBootTest
public class Spring5AutowiredQualifierApplicationTests {
 
    @Autowired(required = false)  //一般在開發環境,不確定是否能注入時用
    private User user1;
 
    @Autowired
    @Qualifier(value = "user1")
    private User user2;
 
    @Autowired
    private User user3;
 
    @Test
    public void testAuto() {
        System.out.println(user2.getName());
        System.out.println(user1.getName());
        System.out.println(user3.getName());
    }
}

@Autowired:spring 中有兩種注入方式,by type/by name,@Autowired 使用 byType 注入,當出現兩個類型一樣的時候,可以顯示的用 @Qualifier 指定名稱,表明用 by name 方式進行注入。否則會注入 @Primary 那個類。如果沒有指定則會報錯。 當不確定系統中是否能注入時,可以使用 required=false,不會強制注入。

@Resource

spring 不但支持自己定義的 @Autowired 注解,還支持幾個由 JSR-250 規范定義的注解,它們分別是 @Resource、@PostConstruct 以及 @PreDestroy。
  @Resource 的作用相當于 @Autowired,只不過 @Autowired 按 byType 自動注入,而 @Resource 默認按 byName 自動注入罷了。@Resource 有兩個屬性是比較重要的,分是 name 和 type,Spring 將 @Resource 注解的name屬性解析為 bean 的名字,而 type 屬性則解析為 bean 的類型。所以如果使用 name 屬性,則使用 byName 的自動注入策略,而使用 type 屬性時則使用 byType 自動注入策略。如果既不指定 name 也不指定 type 屬性,這時將通過反射機制使用 byName 自動注入策略。
  @Resource 裝配順序
  1. 如果同時指定了 name 和 type,則從 Spring 上下文中找到唯一匹配的 bean 進行裝配,找不到則拋出異常
  2. 如果指定了 name,則從上下文中查找名稱(id)匹配的 bean 進行裝配,找不到則拋出異常
  3. 如果指定了 type,則從上下文中找到類型匹配的唯一 bean 進行裝配,找不到或者找到多個,都會拋出異常
  4. 如果既沒有指定 name,又沒有指定 type,則自動按照 byName 方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配;

@Autowired 與 @Resource的區別:

1、 @Autowired 與 @Resource 都可以用來裝配 bean. 都可以寫在字段上,或寫在setter方法上。

2、 @Autowired 默認按類型裝配(這個注解是屬于 spring 的),默認情況下必須要求依賴對象必須存在,如果要允許 null 值,可以設置它的 required 屬性為 false,如:@Autowired(required=false) ,如果我們想使用名稱裝配可以結合 @Qualifier 注解進行使用,如下:

@Autowired()@Qualifier("baseDao")
private BaseDao baseDao;

3、@Resource(這個注解屬于 J2EE 的),默認按照名稱進行裝配,名稱可以通過 name 屬性進行指定,如果沒有指定 name 屬性,當注解寫在字段上時,默認取字段名進行安裝名稱查找,如果注解寫在 setter 方法上默認取屬性名進行裝配。當找不到與名稱匹配的 bean 時才按照類型進行裝配。但是需要注意的是,如果 name 屬性一旦指定,就只會按照名稱進行裝配。

@Resource(name="baseDao")
private BaseDao baseDao;

推薦使用:@Resource 注解在字段上,這樣就不用寫 setter 方法了,并且這個注解是屬于 J2EE 的,減少了與 spring 的耦合。這樣代碼看起就比較優雅。

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

推薦閱讀更多精彩內容