Spring常用注解

Spring的一個(gè)核心功能是IOC,就是將Bean初始化加載到容器中供炼,Bean是如何加載到容器的一屋,可以使用Spring注解方式或者Spring XML配置方式。
Spring注解方式減少了配置文件內(nèi)容袋哼,更加便于管理冀墨,并且使用注解大大提高了開發(fā)效率!
下面按照分類講解Spring中常用的一些注解涛贯。

1.聲明bean的注解(將普通類加入容器形成Bean)
  • @Component 組件诽嘉,沒有明確的角色
  • @Service 在業(yè)務(wù)邏輯層使用(業(yè)務(wù)邏輯層)
  • @Repository 在數(shù)據(jù)訪問層使用(數(shù)據(jù)訪問層)
  • @Controller 在展現(xiàn)層使用,控制器的聲明(頁(yè)面訪問控制層)

這些都是注解在平時(shí)的開發(fā)過程中出鏡率極高弟翘,@Component虫腋、@Repository、@Service稀余、@Controller實(shí)質(zhì)上屬于同一類注解岔乔,用法相同,功能相同滚躯,區(qū)別在于標(biāo)識(shí)組件的類型雏门。@Component可以代替@Repository、@Service掸掏、@Controller茁影,因?yàn)檫@三個(gè)注解是被@Component標(biāo)注的。
如下@controller源碼:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    String value() default "";
}

1丧凤、被注解的java類當(dāng)做Bean實(shí)例募闲,Bean實(shí)例的名稱默認(rèn)是Bean類的首字母小寫,其他部分不變愿待。@Service也可以自定義Bean名稱浩螺,但是必須是唯一的!
2仍侥、盡量使用對(duì)應(yīng)組件注解的類替換@Component注解要出,在spring未來的版本中,@Controller农渊,@Service患蹂,@Repository會(huì)攜帶更多語(yǔ)義。并且便于開發(fā)和維護(hù)!
3传于、指定了某些類可作為Spring Bean類使用后囱挑,最好還需要讓spring搜索指定路徑,在Spring配置文件加入如下配置:

<!-- 自動(dòng)掃描指定包及其子包下的所有Bean類 -->
<context:component-scan base-package="org.springframework.*"/>
2.注入bean的注解(從容器中獲取Bean即裝配bean)

開發(fā)中最常用到的用于裝配的注解是:@Autowired和@Resource

  • @Autowired注解:
    @Autowired源碼:
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, 
ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

@Autowired注解可用于為類的屬性沼溜、構(gòu)造器平挑、方法進(jìn)行注值。默認(rèn)情況下系草,其依賴的對(duì)象必須存在(bean可用)弹惦,如果需要改變這種默認(rèn)方式,可以設(shè)置其required屬性為false悄但。另外一個(gè)比較重要的點(diǎn)就是棠隐,@Autowired注解默認(rèn)按照類型裝配,如果容器中包含多個(gè)同一類型的Bean檐嚣,那么啟動(dòng)容器時(shí)會(huì)報(bào)找不到指定類型bean的異常助泽,解決辦法是結(jié)合@Qualified注解進(jìn)行限定,指定注入的bean名稱嚎京,例如:

public class MovieRecommender {

  @Autowired
  private MovieCatalog movieCatalog;

  private CustomerPreferenceDao customerPreferenceDao;

  @Autowired
  public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
      this.customerPreferenceDao = customerPreferenceDao;
  }
}
@Controller
public class HappyController {
    @Autowired //默認(rèn)依賴的ClubDao 對(duì)象(Bean)必須存在
    //@Autowired(required = false) 改變默認(rèn)方式
    @Qualifier("goodClubService")
    private ClubService clubService;
    
    // Control the people entering the Club
    // do something
}
@Service(value="goodClubService")
//使用@Service注解不加value ,默認(rèn)名稱是clubService
public class ClubServiceImpl implements ClubService {
    @Autowired
    private ClubDao clubDao;
  
    public void doHappy(){
        //do some Happy
    }
 }
  • @Resource注解
    @Resource源碼:
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
 String name() default "";
 Class type() default java.lang.Object.class;

對(duì)于@Resource注解嗡贺,它并不屬于spring的注解,而是來自于JSR-250鞍帝。其默認(rèn)情況下按照bean的名稱進(jìn)行注入诫睬,當(dāng)找不到匹配項(xiàng)時(shí)會(huì)按照類型裝配。當(dāng)按照名稱進(jìn)行裝配時(shí)帕涌,可以指定其name屬性摄凡,倘若沒有指定,注解標(biāo)注在哪個(gè)字段上蚓曼,其默認(rèn)名稱就是那個(gè)字段的名稱亲澡。當(dāng)然,@Resource注解也支持按指定類型進(jìn)行裝配纫版,給它的type屬性賦特定類型的值即可(注意床绪,當(dāng)指定了name屬性后,只能按照名稱裝配)

public class AnotationExp {

    @Resource(name = "HappyClient")
    private HappyClient happyClient;
    
    @Resource(type = HappyPlayAno .class)
    private HappyPlayAno happyPlayAno;
}
  • 總結(jié)

相同點(diǎn):

@Resource的作用相當(dāng)于@Autowired其弊,均可標(biāo)注在字段或?qū)傩缘膕etter方法上癞己。

不同點(diǎn):

a:提供方 @Autowired是Spring的注解,@Resource是javax.annotation注解梭伐,而是來自于JSR-250痹雅,J2EE提供,需要JDK1.6及以上籽御。

b :注入方式 @Autowired只按照Type 注入练慕;@Resource默認(rèn)按Name自動(dòng)注入惰匙,也提供按照Type 注入技掏;

c:屬性
@Autowired注解可用于為類的屬性铃将、構(gòu)造器、方法進(jìn)行注值哑梳。默認(rèn)情況下劲阎,其依賴的對(duì)象必須存在(bean可用),如果需要改變這種默認(rèn)方式鸠真,可以設(shè)置其required屬性為false悯仙。
還有一個(gè)比較重要的點(diǎn)就是,@Autowired注解默認(rèn)按照類型裝配吠卷,如果容器中包含多個(gè)同一類型的Bean锡垄,那么啟動(dòng)容器時(shí)會(huì)報(bào)找不到指定類型bean的異常,解決辦法是結(jié)合@Qualifier注解進(jìn)行限定祭隔,指定注入的bean名稱货岭。
@Resource有兩個(gè)中重要的屬性:name和type。name屬性指定byName疾渴,如果沒有指定name屬性千贯,當(dāng)注解標(biāo)注在字段上,即默認(rèn)取字段的名稱作為bean名稱尋找依賴對(duì)象搞坝,當(dāng)注解標(biāo)注在屬性的setter方法上搔谴,即默認(rèn)取屬性名作為bean名稱尋找依賴對(duì)象。
需要注意的是桩撮,@Resource如果沒有指定name屬性敦第,并且按照默認(rèn)的名稱仍然找不到依賴對(duì)象時(shí), @Resource注解會(huì)回退到按類型裝配店量。但一旦指定了name屬性申尼,就只能按名稱裝配了。

d:@Resource注解的使用性更為靈活垫桂,可指定名稱师幕,也可以指定類型 ;@Autowired注解進(jìn)行裝配容易拋出異常诬滩,特別是裝配的bean類型有多個(gè)的時(shí)候霹粥,而解決的辦法是需要在增加@Qualifier進(jìn)行限定。

3. Java配置類相關(guān)注解
  • @Configuration 聲明當(dāng)前類為配置類疼鸟,其中內(nèi)部組合了@Component注解后控,表明這個(gè)類是一個(gè)bean相當(dāng)于xml形式的Spring配置(類上)
    Spring的官方團(tuán)隊(duì)說@Component可以替代 @Configuration注解,事實(shí)上我們看源碼也可以發(fā)現(xiàn)看到空镜,如下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component  //看這里:铺浴0破印!
public @interface Configuration {
    String value() default "";
  • @Bean 注解在方法上张抄,聲明當(dāng)前方法的返回值為一個(gè)bean砂蔽,替代xml中的方式(方法上)
  • @ComponentScan 用于對(duì)Component進(jìn)行掃描,相當(dāng)于xml中的context:component-scan/(類上)
  • @WishlyConfiguration 為@Configuration與@ComponentScan的組合注解署惯,可以替代這兩個(gè)注解
4.Spring @Configuration與@Component的區(qū)別

代碼如下:

@Configuration
public static class Config {

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean());
    }
}
@Component
public static class Config {

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean());
    }
}

第一段代碼可以正常運(yùn)行左驾,并且可以預(yù)期地從SimpleBeanConsumer獲得指向singleton的鏈接SimpleBean。但是不幸的是极谊,它在簽名環(huán)境中不起作用诡右。

第二個(gè)配置是完全錯(cuò)誤的,因?yàn)镾pring會(huì)創(chuàng)建一個(gè)SimpleBean的單例bean轻猖,但是SimpleBeanConsumer將獲得另一個(gè)SimpleBean實(shí)例(也就是相當(dāng)于直接調(diào)用new SimpleBean() 帆吻,這個(gè)bean是不歸Spring管理的),既new SimpleBean() 實(shí)例是Spring上下文控件之外的咙边。

這種現(xiàn)象的原因可以解釋如下:

如果使用@Configuration猜煮,則所有標(biāo)記為的方法@Bean都將被包裝到CGLIB包裝器中,該包裝器將像第一次調(diào)用此方法一樣工作样眠,然后將執(zhí)行原始方法的主體友瘤,并將結(jié)果對(duì)象注冊(cè)在spring上下文中。所有其他調(diào)用僅返回從上下文中檢索到的bean檐束。

在上面的第二個(gè)代碼塊中辫秧,new SimpleBeanConsumer(simpleBean())僅調(diào)用一個(gè)純java方法。要更正第二個(gè)代碼塊被丧,我們可以執(zhí)行以下操作:

@Component
public static class Config {
    @Autowired
    SimpleBean simpleBean;

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean);
    }
}
  • 原因總結(jié)

使用@ configuration盟戏,所有標(biāo)記為@ bean的方法將被包裝成一個(gè)CGLIB包裝器,它的工作方式就好像是這個(gè)方法的第一個(gè)調(diào)用甥桂,那么原始方法的主體將被執(zhí)行柿究,最終的對(duì)象將在spring上下文中注冊(cè)。所有進(jìn)一步的調(diào)用只返回從上下文檢索的bean黄选。

Spring注解——使用@ComponentScan自動(dòng)掃描組件

5.切面(AOP)相關(guān)注解

Spring支持AspectJ的注解式切面編程蝇摸。

  • @EnableAspectJAutoProxy 開啟基于注解的aop模式
  • @Aspect 聲明一個(gè)切面(類上)
  • @After 在方法執(zhí)行之后執(zhí)行(方法上)
  • @Before 在方法執(zhí)行之前執(zhí)行(方法上)
  • @Around 在方法執(zhí)行之前與之后執(zhí)行(方法上)
  • @PointCut 聲明切點(diǎn)
  • @EnableAspectJAutoProxy在java配置類中使用該注解開啟Spring對(duì)AspectJ代理的支持(類上)
6.@Bean的屬性支持
  • @Scope 設(shè)置Spring容器如何新建Bean實(shí)例(方法上,必須有@Bean)
    其設(shè)置類型包括:

Singleton (單例,一個(gè)Spring容器中只有一個(gè)bean實(shí)例办陷,默認(rèn)模式),
Protetype (每次調(diào)用新建一個(gè)bean),
Request (web項(xiàng)目中貌夕,給每個(gè)http request新建一個(gè)bean),
Session (web項(xiàng)目中,給每個(gè)http session新建一個(gè)bean),
GlobalSession(給每一個(gè) global http session新建一個(gè)Bean實(shí)例)

  • @StepScope 在Spring Batch中還有涉及
  • @Qualifier注解定義Bean名稱(方法上民镜,必須有@Bean)啡专。
    當(dāng)你創(chuàng)建多個(gè)具有相同類型的 bean 時(shí),并且想要用一個(gè)屬性只為它們其中的一個(gè)進(jìn)行裝配制圈,在這種情況下们童,你可以使用 @Qualifier 注釋和 @Autowired 注釋通過指定哪一個(gè)真正的 bean 將會(huì)被裝配來消除混亂畔况。
  • @PostConstruct 用來標(biāo)記是在項(xiàng)目啟動(dòng)的時(shí)候執(zhí)行這個(gè)方法。用來修飾一個(gè)非靜態(tài)的void()方法
    也就是spring容器啟動(dòng)時(shí)就執(zhí)行慧库,多用于一些全局配置跷跪、數(shù)據(jù)字典之類的加載。
    被@PostConstruct修飾的方法會(huì)在服務(wù)器加載Servlet的時(shí)候運(yùn)行完沪,并且只會(huì)被服務(wù)器執(zhí)行一次域庇。PostConstruct在構(gòu)造函數(shù)之后執(zhí)行,init()方法之前執(zhí)行嵌戈。PreDestroy()方法在destroy()方法執(zhí)行執(zhí)行之后執(zhí)
  • @PreDestory 被@PreDestroy修飾的方法會(huì)在服務(wù)器卸載Servlet的時(shí)候運(yùn)行覆积,并且只會(huì)被服務(wù)器調(diào)用一次,類似于Servlet的destroy()方法熟呛。被@PreDestroy修飾的方法會(huì)在destroy()方法之后運(yùn)行宽档,在Servlet被徹底卸載之前
7.@Value注解

@Value 為屬性注入值(屬性上)
示例:

注入普通字符:
@Value("Michael Jackson")
String name;

注入操作系統(tǒng)屬性:
@Value("#{systemProperties['os.name']}")
String osName;

注入表達(dá)式結(jié)果:
@Value("#{ T(java.lang.Math).random() * 100 }")
String randomNumber;

注入其它bean屬性:
@Value("#{domeClass.name}")
String name;

注入文件資源:
@Value("classpath:com/hgs/hello/test.txt")
String Resource file;

注入網(wǎng)站資源:
@Value("http://www.cznovel.com")
Resource url;

注入配置文件:
@Value("${book.name}")
String bookName;

注入配置使用方法:
① 編寫配置文件(test.properties)
book.name=《三體》
② @PropertySource 加載配置文件(類上)
@PropertySource("classpath:com/hgs/hello/test/test.propertie")
③ 還需配置一個(gè)PropertySourcesPlaceholderConfigurer的bean。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末庵朝,一起剝皮案震驚了整個(gè)濱河市吗冤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌九府,老刑警劉巖椎瘟,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異侄旬,居然都是意外死亡肺蔚,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門儡羔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宣羊,“玉大人,你說我怎么就攤上這事汰蜘〕鸱耄” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵族操,是天一觀的道長(zhǎng)苛坚。 經(jīng)常有香客問我,道長(zhǎng)色难,這世上最難降的妖魔是什么泼舱? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮莱预,結(jié)果婚禮上柠掂,老公的妹妹穿的比我還像新娘。我一直安慰自己依沮,他們只是感情好涯贞,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布枪狂。 她就那樣靜靜地躺著,像睡著了一般宋渔。 火紅的嫁衣襯著肌膚如雪州疾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天皇拣,我揣著相機(jī)與錄音严蓖,去河邊找鬼。 笑死氧急,一個(gè)胖子當(dāng)著我的面吹牛颗胡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吩坝,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼毒姨,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了钉寝?” 一聲冷哼從身側(cè)響起弧呐,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嵌纲,沒想到半個(gè)月后俘枫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逮走,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年鸠蚪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片言沐。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邓嘹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出险胰,到底是詐尸還是另有隱情汹押,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布起便,位于F島的核電站棚贾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏榆综。R本人自食惡果不足惜妙痹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鼻疮。 院中可真熱鬧怯伊,春花似錦、人聲如沸判沟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吧秕,卻和暖如春琉闪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背砸彬。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工颠毙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砂碉。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓蛀蜜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親绽淘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涵防,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容