使用Spring實(shí)現(xiàn)依賴注入

基本條件:所有的類要被spring所管理才能進(jìn)行依賴注入

A. 依賴注入

我們以下面這個(gè)例子說(shuō)明如何進(jìn)行依賴注入:


代碼準(zhǔn)備:
interfaces:

/**
 * 有機(jī)箱
 */
public interface IComputerCase {
    public String sysComputerCaseName();
}

/**
 * 鍵盤鼠標(biāo)
 */
public interface IKeyboard {
    public String sysKeyboardName();
}

/**
 * 顯示器
 */
public interface IMonitor {
    public String sysMonitorName();
}

entity:

public class Acer implements IMonitor {
    public String sysMonitorName() {
        return "宏基";
    }
}

public class BenQ implements IMonitor {
    public String sysMonitorName() {
        return "明基";
    }
}

public class Bubalus implements IComputerCase {
    public String sysComputerCaseName() {
        return "大水牛";
    }
}

public class GoldenField implements IComputerCase {
    public String sysComputerCaseName() {
        return "金和田";
    }
}

public class Logitech implements IKeyboard {
    public String sysKeyboardName() {
        return "羅技";
    }
}

public class Rapoo implements IKeyboard {
    public String sysKeyboardName() {
        return "雷柏";
    }
}

1.使用set注入(最常用的方式)

通過setxx方法注入:property

1.1 提供相應(yīng)要注入的類的setter

public class Computer1 {

    private IComputerCase computerCase;
    private IKeyboard keyboard;
    private IMonitor monitor;

    public IComputerCase getComputerCase() {
        return computerCase;
    }

    //提供要注入的類的set方法
    public void setComputerCase(IComputerCase computerCase) {
        this.computerCase = computerCase;
    }

    public IKeyboard getKeyboard() {
        return keyboard;
    }

    //提供要注入的類的set方法
    public void setKeyboard(IKeyboard keyboard) {
        this.keyboard = keyboard;
    }

    public IMonitor getMonitor() {
        return monitor;
    }

    //提供要注入的類的set方法
    public void setMonitor(IMonitor monitor) {
        this.monitor = monitor;
    }
}

1.2 在配置文件中注入
??name中的值會(huì)在Computer對(duì)象中調(diào)用setXX方法來(lái)注入(所以方法名稱不能變)斑司。比如注入name="computerCase"在具體注入時(shí)會(huì)回調(diào)用setComputerCase來(lái)完成注入神妹。ref="ComputerCase1"表示是配置文件中的bean中所創(chuàng)建的ComputerCase1的id僻肖。

<?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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <bean id="ComputerCase1" class="com.IOCExercise.entity.Bubalus"/>
    <bean id="ComputerCase2" class="com.IOCExercise.entity.GoldenField"/>

    <bean id="Keyboard1" class="com.IOCExercise.entity.Logitech"/>
    <bean id="Keyboard2" class="com.IOCExercise.entity.Rapoo"/>

    <bean id="Monitor1" class="com.IOCExercise.entity.Acer"/>
    <bean id="Monitor2" class="com.IOCExercise.entity.BenQ"/>

    <bean id="Computer1" class="com.IOCExercise.test.Computer1">
       <!--向Computer1注入computerCase-->
       <property name="computerCase" ref="ComputerCase1" />
       <!--向Computer1注入keyboard-->
       <property name="keyboard" ref="Keyboard1" />
       <!--向Computer1注入monitor-->
       <property name="monitor" ref="Monitor1" />
     </bean>
</beans>

1.3 測(cè)試

public class Computer1SetterTest {

    public static void main(String[] args) {
        //以ApplicationContext方式
        ApplicationContext context=
                new ClassPathXmlApplicationContext("bean1.xml");
        Computer1 aComputer1=(Computer1)context.getBean("Computer1");
        System.out.println("computer1's computercase:"+aComputer1.getComputerCase().sysComputerCaseName());
        System.out.println("computer1's keyboard:"+aComputer1.getKeyboard().sysKeyboardName());
        System.out.println("computer1's monitor:"+aComputer1.getMonitor().sysMonitorName());
}

2. 基于構(gòu)造函數(shù)的注入(了解)

通過構(gòu)造函數(shù)注入:constructor-arg

這種方式的注入是指帶有參數(shù)的構(gòu)造函數(shù)注入,如果未設(shè)置對(duì)象的set方法,所以就不能支持第一種注入方式惹谐。這里的注入方式是在構(gòu)造函數(shù)中注入碾篡,也就是說(shuō)在創(chuàng)建Computer2 對(duì)象時(shí)要將computerCase、keyboard和monitor這三個(gè)參數(shù)值傳進(jìn)來(lái)蹂喻。

2.1 提供相應(yīng)要注入的類的構(gòu)造方法

public class Computer2 {

    public IComputerCase computerCase;

    public IKeyboard keyboard;

    public IMonitor monitor;

    public Computer2(IComputerCase computerCase,IKeyboard keyboard,IMonitor monitor)
    {
        this.computerCase = computerCase;
        this.keyboard = keyboard;
        this.monitor = monitor;
    }
}

2.2 在配置文件中注入
??在XML文件中同樣不用<property>的形式葱椭,而是使用<constructor-arg>標(biāo)簽,ref屬性同樣指向其它<bean>標(biāo)簽的name屬性:

<?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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <bean id="ComputerCase1" class="com.IOCExercise.entity.Bubalus"/>
    <bean id="ComputerCase2" class="com.IOCExercise.entity.GoldenField"/>

    <bean id="Keyboard1" class="com.IOCExercise.entity.Logitech"/>
    <bean id="Keyboard2" class="com.IOCExercise.entity.Rapoo"/>

    <bean id="Monitor1" class="com.IOCExercise.entity.Acer"/>
    <bean id="Monitor2" class="com.IOCExercise.entity.BenQ"/>

    <bean id="Computer2" class="com.IOCExercise.test.Computer2">
        <constructor-arg ref="ComputerCase2"/>
        <constructor-arg ref="Keyboard2"/>
        <constructor-arg ref="Monitor2"/>
    </bean>
</beans>

當(dāng)構(gòu)造函數(shù)有多個(gè)參數(shù)時(shí)口四,可以使用constructor-arg標(biāo)簽的index屬性孵运,index屬性的值從0開始。下面是設(shè)置index蔓彩,就是參數(shù)位置:

    <bean id="Computer2" class="com.IOCExercise.test.Computer2">
        <constructor-arg index="0" ref="ComputerCase2"/>
        <constructor-arg index="1" ref="Keyboard2"/>
        <constructor-arg index="2" ref="Monitor2"/>
    </bean>

2.3 測(cè)試

public class Computer2ConsTest {

    public static void main(String[] args) {
        //以ApplicationContext方式
        ApplicationContext context=
                new ClassPathXmlApplicationContext("bean1.xml");
        Computer2 aComputer2=(Computer2)context.getBean("Computer2");
        System.out.println("computer2's computercase:"+aComputer2.computerCase.sysComputerCaseName());
        System.out.println("computer2's keyboard:"+aComputer2.keyboard.sysKeyboardName());
        System.out.println("computer2's monitor:"+aComputer2.monitor.sysMonitorName());
}

B. 屬性注入和自動(dòng)注入

1. 屬性注入
以下面的例子說(shuō)明如何進(jìn)行屬性注入:

![Upload Paste_Image.png failed. Please try again.]

Classes類:

public class Classes {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Student類:

public class Student {
    //姓名
    private String name;
    //學(xué)號(hào)
    private int sno;
    //班級(jí)
    private Classes classes;
    //課程分?jǐn)?shù)
    private double[] score;
   //課程列表
    private List<String> course;
    private Set<String> hobby;
    private Map other;

    //setter治笨、getter
}

bean.xml

<?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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <bean id="Classes3" class="com.IOCExercise.entity.Classes">
        <property name="name" value="軟件R3班" />
    </bean>

    <bean id="Student" class="com.IOCExercise.entity.Student">
        <!--通過value可以注入一個(gè)基本數(shù)據(jù)類型-->
        <property name="name" value="zoyoto" />
        <property name="sno" value="26" />
        <!--引用Spring中定義的classes對(duì)象-->
        <property name="classes" ref="Classes3" />
        <!--注入數(shù)組-->
        <property name="score">
            <array>
                <value>91</value>
                <value>88</value>
            </array>
        </property>
        <!--注入list-->
        <property name="course">
            <list>
                <value>語(yǔ)文</value>
                <value>數(shù)學(xué)</value>
            </list>
        </property>
        <!--注入Set-->
        <property name="hobby">
            <set>
                <value>畫畫</value>
                <value>羽毛球</value>
            </set>
        </property>
        <!--注入Map-->
        <property name="other">
            <map>
                <entry key="beijing" value="北京"></entry>
                <entry key="guangzhou" value="廣州" ></entry>
            </map>
        </property>
    </bean>
</beans>

2. 自動(dòng)注入(一般不使用)

  • byName是根據(jù)set的名稱注入的,如果名稱不對(duì)就無(wú)法注入(默認(rèn)情況)
  • byType是根據(jù)類型來(lái)注入的赤嚼,和名稱無(wú)關(guān)旷赖,如果一個(gè)類中有兩個(gè)相同類型的對(duì)象則無(wú)法注入。

如果要使用一般使用byName:


C. 基于annotation的注入

使用@Resource更卒、@Autowired等孵、@Repository、@Service蹂空、@Controller 和 @Component可以將類標(biāo)識(shí)為 Bean俯萌。

annotation介紹

@Resource
??@Resource就相當(dāng)于application.getBean()方法。@Resource有兩個(gè)中重要的屬性:name和type 上枕,而Spring將@Resource注解的name屬性解析為bean的名字咐熙,而type屬性則解析為bean的類型。所以如果使用name屬性姿骏,則使用byName的自動(dòng)注入策略糖声,而使用type屬性時(shí)則使用 byType自動(dòng)注入策略。如果既不指定name也不指定type屬性,這時(shí)將通過反射機(jī)制使用byName自動(dòng)注入策略蘸泻。

@Autowired
??@Autowired作用和@Resource一樣琉苇,但@Autowired默認(rèn)按類型裝配(這個(gè)注解是屬業(yè)spring的),默認(rèn)情況下必須要求依賴對(duì)象必須存在悦施,如果要允許null 值并扇,可以設(shè)置它的required屬性為false,如:@Autowired(required=false) 抡诞,如果我們想使用名稱裝配可以結(jié)合@Qualifier注解進(jìn)行使用,如下:

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

@Component
??是一個(gè)泛華的概念昼汗,僅僅表示一個(gè)組件肴熏,可以作用于任何層次顷窒。

@Repository
??只能標(biāo)注在DAO層,這是因?yàn)樵撟⒔獾淖饔貌恢皇菍㈩愖R(shí)別為Bean鞋吉,同時(shí)它還能將所標(biāo)注的類中拋出的數(shù)據(jù)訪問異常封裝為Spring的數(shù)據(jù)訪問異常類型

@Service
??通常作用在業(yè)務(wù)層,但是目前該功能與@Component相同谓着。

@Controller
??通常作用在控制層,但是目前該功能與@Component相同赊锚。

1.設(shè)置bean.xml的schema


2.在類上面設(shè)置


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市改抡,隨后出現(xiàn)的幾起案子矢炼,更是在濱河造成了極大的恐慌,老刑警劉巖阿纤,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件句灌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡欠拾,警方通過查閱死者的電腦和手機(jī)胰锌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)藐窄,“玉大人资昧,你說(shuō)我怎么就攤上這事【H蹋” “怎么了格带?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵撤缴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我叽唱,道長(zhǎng)屈呕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任棺亭,我火速辦了婚禮虎眨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘镶摘。我一直安慰自己嗽桩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布凄敢。 她就那樣靜靜地躺著碌冶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贡未。 梳的紋絲不亂的頭發(fā)上种樱,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音俊卤,去河邊找鬼。 笑死害幅,一個(gè)胖子當(dāng)著我的面吹牛消恍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播以现,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狠怨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了邑遏?” 一聲冷哼從身側(cè)響起佣赖,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤记盒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后纪吮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棚辽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年冰肴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了榔组。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片联逻。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡遣妥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出箫踩,到底是詐尸還是另有隱情,我是刑警寧澤境钟,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站洞渔,受9級(jí)特大地震影響缚态,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜玫芦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望医增。 院中可真熱鬧,春花似錦叶骨、人聲如沸祈匙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至歉甚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纸泄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工聘裁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衡便。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓镣陕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親呆抑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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