[Spring]基于注解的IoC容器配置

概述

Spring2.5 引入了注解。
于是且预,一個問題產(chǎn)生了:使用注解方式注入 JavaBean 是不是一定完爆 xml方式耙册?
未必给僵。正所謂,仁者見仁智者見智详拙。任何事物都有其優(yōu)缺點帝际,看你如何取舍。來看看注解的優(yōu)缺點:
優(yōu)點:大大減少了配置饶辙,并且可以使配置更加精細——類蹲诀,方法,字段都可以用注解去標記弃揽。
缺點:使用注解脯爪,不可避免產(chǎn)生了侵入式編程,也產(chǎn)生了一些問題矿微。

  • 你需要將注解加入你的源碼并編譯它痕慢;
  • 注解往往比較分散,不易管控涌矢。

注:spring 中掖举,先進行注解注入,然后才是xml注入蒿辙,因此如果注入的目標相同拇泛,后者會覆蓋前者滨巴。

啟動注解

Spring 默認是不啟用注解的思灌。如果想使用注解,需要先在xml中啟動注解恭取。
啟動方式:在xml中加入一個標簽泰偿,很簡單吧。

<context:annotation-config/>

注:<context:annotation-config/> 只會檢索定義它的上下文蜈垮。什么意思呢耗跛?就是說裕照,如果你
為DispatcherServlet指定了一個WebApplicationContext,那么它只在controller中查找@Autowired注解调塌,而不會檢查其它的路徑晋南。

Spring注解

@Required

@Required 注解只能用于修飾bean屬性的setter方法。受影響的bean屬性必須在配置時被填充在xml配置文件中羔砾,否則容器將拋出BeanInitializationException负间。

public class AnnotationRequired {
    private String name;
    private String sex;

    public String getName() {
        return name;
    }

    /**
     * @Required 注解用于bean屬性的setter方法并且它指示,受影響的bean屬性必須在配置時被填充在xml配置文件中姜凄,
     *           否則容器將拋出BeanInitializationException政溃。
     */
    @Required
    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

@Autowired

@Autowired注解可用于修飾屬性、setter方法态秧、構(gòu)造方法董虱。

注:@Autowired注解也可用于修飾構(gòu)造方法,但如果類中只有默認構(gòu)造方法申鱼,則沒有必要愤诱。如果有多個構(gòu)造器,至少應該修飾一個捐友,來告訴容器哪一個必須使用转锈。

可以使用JSR330的注解@Inject來替代@Autowired

范例

public class AnnotationAutowired {
    private static final Logger log = LoggerFactory.getLogger(AnnotationRequired.class);

    @Autowired
    private Apple fieldA;

    private Banana fieldB;

    private Orange fieldC;

    public Apple getFieldA() {
        return fieldA;
    }

    public void setFieldA(Apple fieldA) {
        this.fieldA = fieldA;
    }

    public Banana getFieldB() {
        return fieldB;
    }

    @Autowired
    public void setFieldB(Banana fieldB) {
        this.fieldB = fieldB;
    }

    public Orange getFieldC() {
        return fieldC;
    }

    public void setFieldC(Orange fieldC) {
        this.fieldC = fieldC;
    }

    public AnnotationAutowired() {}

    @Autowired
    public AnnotationAutowired(Orange fieldC) {
        this.fieldC = fieldC;
    }

    public static void main(String[] args) throws Exception {
        AbstractApplicationContext ctx =
                        new ClassPathXmlApplicationContext("spring/spring-annotation.xml");

        AnnotationAutowired annotationAutowired =
                        (AnnotationAutowired) ctx.getBean("annotationAutowired");
        log.debug("fieldA: {}, fieldB:{}, fieldC:{}", annotationAutowired.getFieldA().getName(),
                        annotationAutowired.getFieldB().getName(),
                        annotationAutowired.getFieldC().getName());
        ctx.close();
    }
}

xml中的配置

<!-- 測試@Autowired -->
<bean id="apple" class="org.zp.notes.spring.beans.annotation.sample.Apple"/>
<bean id="potato" class="org.zp.notes.spring.beans.annotation.sample.Banana"/>
<bean id="tomato" class="org.zp.notes.spring.beans.annotation.sample.Orange"/>
<bean id="annotationAutowired" class="org.zp.notes.spring.beans.annotation.sample.AnnotationAutowired"/>

@Qualifier

@Autowired注解中楚殿,提到了如果發(fā)現(xiàn)有多個候選的bean都符合修飾類型撮慨,Spring就會抓瞎了。

那么脆粥,如何解決這個問題砌溺。

可以通過@Qualifier指定bean名稱來鎖定真正需要的那個bean。

范例

public class AnnotationQualifier {
    private static final Logger log = LoggerFactory.getLogger(AnnotationQualifier.class);

    @Autowired
    @Qualifier("dog") /** 去除這行变隔,會報異常 */
    Animal dog;

    Animal cat;

    public Animal getDog() {
        return dog;
    }

    public void setDog(Animal dog) {
        this.dog = dog;
    }

    public Animal getCat() {
        return cat;
    }

    @Autowired
    public void setCat(@Qualifier("cat") Animal cat) {
        this.cat = cat;
    }

    public static void main(String[] args) throws Exception {
        AbstractApplicationContext ctx =
                new ClassPathXmlApplicationContext("spring/spring-annotation.xml");

        AnnotationQualifier annotationQualifier =
                (AnnotationQualifier) ctx.getBean("annotationQualifier");

        log.debug("Dog name: {}", annotationQualifier.getDog().getName());
        log.debug("Cat name: {}", annotationQualifier.getCat().getName());
        ctx.close();
    }
}

abstract class Animal {
    public String getName() {
        return null;
    }
}

class Dog extends Animal {
    public String getName() {
        return "狗";
    }
}

class Cat extends Animal {
    public String getName() {
        return "貓";
    }
}

xml中的配置

<!-- 測試@Qualifier -->
<bean id="dog" class="org.zp.notes.spring.beans.annotation.sample.Dog"/>
<bean id="cat" class="org.zp.notes.spring.beans.annotation.sample.Cat"/>
<bean id="annotationQualifier" class="org.zp.notes.spring.beans.annotation.sample.AnnotationQualifier"/>

JSR 250注解

@Resource

Spring支持 JSP250規(guī)定的注解@Resource规伐。這個注解根據(jù)指定的名稱來注入bean。

如果沒有為@Resource指定名稱匣缘,它會像@Autowired一樣按照類型去尋找匹配猖闪。

在Spring中,由CommonAnnotationBeanPostProcessor來處理@Resource注解肌厨。

范例

public class AnnotationResource {
    private static final Logger log = LoggerFactory.getLogger(AnnotationResource.class);

    @Resource(name = "flower")
    Plant flower;

    @Resource(name = "tree")
    Plant tree;

    public Plant getFlower() {
        return flower;
    }

    public void setFlower(Plant flower) {
        this.flower = flower;
    }

    public Plant getTree() {
        return tree;
    }

    public void setTree(Plant tree) {
        this.tree = tree;
    }

    public static void main(String[] args) throws Exception {
        AbstractApplicationContext ctx =
                        new ClassPathXmlApplicationContext("spring/spring-annotation.xml");

        AnnotationResource annotationResource =
                        (AnnotationResource) ctx.getBean("annotationResource");
        log.debug("type: {}, name: {}", annotationResource.getFlower().getClass(), annotationResource.getFlower().getName());
        log.debug("type: {}, name: {}", annotationResource.getTree().getClass(), annotationResource.getTree().getName());
        ctx.close();
    }
}

xml的配置

<!-- 測試@Resource -->
<bean id="flower" class="org.zp.notes.spring.beans.annotation.sample.Flower"/>
<bean id="tree" class="org.zp.notes.spring.beans.annotation.sample.Tree"/>
<bean id="annotationResource" class="org.zp.notes.spring.beans.annotation.sample.AnnotationResource"/>

@PostConstruct和@PreDestroy

@PostConstruct@PreDestroy是JSR 250規(guī)定的用于生命周期的注解培慌。

從其名號就可以看出,一個是在構(gòu)造之后調(diào)用的方法柑爸,一個是銷毀之前調(diào)用的方法吵护。

public class AnnotationPostConstructAndPreDestroy {
    private static final Logger log = LoggerFactory.getLogger(AnnotationPostConstructAndPreDestroy.class);

    @PostConstruct
    public void init() {
        log.debug("call @PostConstruct method");
    }

    @PreDestroy
    public void destroy() {
        log.debug("call @PreDestroy method");
    }
}

JSR 330注解

從Spring3.0開始,Spring支持JSR 330標準注解(依賴注入)。

注:如果要使用JSR 330注解馅而,需要使用外部jar包祥诽。

若你使用maven管理jar包,只需要添加依賴到pom.xml即可:

<dependency>
  <groupId>javax.inject</groupId>
  <artifactId>javax.inject</artifactId>
  <version>1</version>
</dependency>

@Inject

@Inject@Autowired一樣瓮恭,可以修飾屬性雄坪、setter方法、構(gòu)造方法屯蹦。

范例

public class AnnotationInject {
    private static final Logger log = LoggerFactory.getLogger(AnnotationInject.class);
    @Inject
    Apple fieldA;

    Banana fieldB;

    Orange fieldC;

    public Apple getFieldA() {
        return fieldA;
    }

    public void setFieldA(Apple fieldA) {
        this.fieldA = fieldA;
    }

    public Banana getFieldB() {
        return fieldB;
    }

    @Inject
    public void setFieldB(Banana fieldB) {
        this.fieldB = fieldB;
    }

    public Orange getFieldC() {
        return fieldC;
    }

    public AnnotationInject() {}

    @Inject
    public AnnotationInject(Orange fieldC) {
        this.fieldC = fieldC;
    }

    public static void main(String[] args) throws Exception {
        AbstractApplicationContext ctx =
                        new ClassPathXmlApplicationContext("spring/spring-annotation.xml");
        AnnotationInject annotationInject = (AnnotationInject) ctx.getBean("annotationInject");

        log.debug("type: {}, name: {}", annotationInject.getFieldA().getClass(),
                        annotationInject.getFieldA().getName());

        log.debug("type: {}, name: {}", annotationInject.getFieldB().getClass(),
                        annotationInject.getFieldB().getName());

        log.debug("type: {}, name: {}", annotationInject.getFieldC().getClass(),
                        annotationInject.getFieldC().getName());

        ctx.close();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诸衔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子颇玷,更是在濱河造成了極大的恐慌笨农,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帖渠,死亡現(xiàn)場離奇詭異谒亦,居然都是意外死亡,警方通過查閱死者的電腦和手機空郊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門份招,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狞甚,你說我怎么就攤上這事锁摔。” “怎么了哼审?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵谐腰,是天一觀的道長。 經(jīng)常有香客問我涩盾,道長十气,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任春霍,我火速辦了婚禮砸西,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘址儒。我一直安慰自己芹枷,他們只是感情好,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布莲趣。 她就那樣靜靜地躺著鸳慈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妖爷。 梳的紋絲不亂的頭發(fā)上蝶涩,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天理朋,我揣著相機與錄音絮识,去河邊找鬼绿聘。 笑死,一個胖子當著我的面吹牛次舌,可吹牛的內(nèi)容都是我干的熄攘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼彼念,長吁一口氣:“原來是場噩夢啊……” “哼挪圾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起逐沙,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤哲思,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吩案,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棚赔,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年徘郭,在試婚紗的時候發(fā)現(xiàn)自己被綠了靠益。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡残揉,死狀恐怖胧后,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抱环,我是刑警寧澤壳快,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站镇草,受9級特大地震影響濒憋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜陶夜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一凛驮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧条辟,春花似錦黔夭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至杭棵,卻和暖如春婚惫,著一層夾襖步出監(jiān)牢的瞬間氛赐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工先舷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留艰管,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓蒋川,卻偏偏與公主長得像牲芋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捺球,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

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