spring ioc

1、IoC 依賴注入(控制反轉(zhuǎn)) 方便解耦

耦合:
業(yè)務(wù)層的A類中要使用持久層B類對(duì)象,于是在A類中new了一個(gè)B類對(duì)象來(lái)用,這就導(dǎo)致了A類會(huì)強(qiáng)依賴于B類,產(chǎn)生耦合,耦合只能減弱不能消除,消除相當(dāng)于這兩個(gè)類毫無(wú)關(guān)系了。
減弱耦合:
不在A類中newB類的對(duì)象,建立一個(gè)對(duì)象容器(工廠),這個(gè)容器里面就產(chǎn)生各種對(duì)象給別的類調(diào)用,對(duì)象的生成只在這個(gè)容器中,可以把要生成的對(duì)象path寫在properties或xml文件中,在容器中用靜態(tài)代碼塊讀取properties或xml中的內(nèi)容,通過(guò)反射生成對(duì)象,保存在容器中,比如一個(gè)Map中,再向外界提供一個(gè)根據(jù)map的key獲取對(duì)象的方法。

1、1那么spring是如何做到減弱耦合的呢?

原理和上面的對(duì)象容器工廠差不多,容器由spring完成了,我們只需要在xml中配置業(yè)務(wù)層和持久層的對(duì)象信息:說(shuō)明要?jiǎng)?chuàng)建哪個(gè)對(duì)象、用什么方式去?。?/p>

    <bean id=“accountService” class=“com.demo.service.impl.AccountServiceImpl”><bean/>
    <bean id=“accountDao” class=“com.demo.dao.impl.AccountDaoImpl”><bean/>
    id:對(duì)象的唯一標(biāo)示;class:要?jiǎng)?chuàng)建對(duì)象的全限定類名

spring有一個(gè)核心容器,xml中讀取的對(duì)象都生成放在核心容器中;下面我們只需要獲取到核心容器后,再根據(jù)bean的id獲取對(duì)象:

核心容器類:
    ApplicationContext:
        是BeanFactory下的子接口的再子接口。
        特點(diǎn)是創(chuàng)建bean對(duì)象時(shí),采用的是立即加載的策略。(當(dāng)讀取完xml配置文件,配置文件中所有的bean對(duì)象都已經(jīng)創(chuàng)建完成了,實(shí)測(cè))
    BeanFactory:
        它是springioc容器的頂層接口。
        特點(diǎn)是創(chuàng)建bean對(duì)象時(shí),采用的是延遲加載的策略。(當(dāng)真正要從容器獲取bean對(duì)象時(shí)才創(chuàng)建,讀完配置文件時(shí)不創(chuàng)建)
    單例對(duì)象可以用ApplicationContext,多例對(duì)象用BeanFactory,不過(guò)spring會(huì)幫我們處理,一般都用ApplicationContext,設(shè)置屬性可以選擇單例多例。
  • 用bean標(biāo)簽創(chuàng)建bean對(duì)象三種創(chuàng)建方式:
    1、通過(guò)調(diào)用默認(rèn)構(gòu)造函數(shù)來(lái)創(chuàng)建bean對(duì)象,默認(rèn)情況下,在bean標(biāo)簽中寫了class屬性,spring就會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù)創(chuàng)建對(duì)象,如果沒(méi)有默認(rèn)構(gòu)造函數(shù),則對(duì)象創(chuàng)建失敗:
    <bean id=“唯一標(biāo)示” class=“全限定類名”></bean>

2、靜態(tài)工廠創(chuàng)建,項(xiàng)目中已經(jīng)有一個(gè)創(chuàng)建對(duì)象的工廠類,其中有創(chuàng)建對(duì)象的靜態(tài)方法可以使用:
<bean id=“唯一標(biāo)示” class=“全限定類名(工廠類)” factory-method=“方法名”></bean>

3、實(shí)例工廠創(chuàng)建,項(xiàng)目中已經(jīng)有一個(gè)創(chuàng)建對(duì)象的工廠類,其中有創(chuàng)建對(duì)象的非靜態(tài)方法可以使用:

<bean id=“唯一標(biāo)示” factory-bean=“工廠bean的id”  factory-method=“方法名”></bean>
  • bean對(duì)象的作用范圍:
    可以通過(guò)一個(gè)配置屬性來(lái)指定:scope屬性: 比如 scope=“singleton”
    有幾個(gè)值:
    singleton:?jiǎn)卫?(默認(rèn)值,也最常用)
    prototype:多例的
    request:請(qǐng)求范圍
    session:會(huì)話范圍
    global-session:全局會(huì)話范圍

  • Bean對(duì)象的生命周期:
    單例對(duì)象
    出生:容器創(chuàng)建,對(duì)象出生
    活著:只要容器在,對(duì)象就一直可用
    死亡:容器銷毀,對(duì)象消亡
    多例對(duì)象
    出生:每次使用時(shí),容器才會(huì)為我們創(chuàng)建對(duì)象
    活著:只要對(duì)象在使用過(guò)程中就一直活著
    死亡:spring不知道對(duì)象你什么時(shí)候用完,spring把這件事交給了java的gc:對(duì)象長(zhǎng)時(shí)間不用,并且也沒(méi)有其他對(duì)象引用時(shí),java的垃圾回收器回收

1、2對(duì)象創(chuàng)建出來(lái)了,那么依賴關(guān)系要怎么構(gòu)建呢,spring提供了依賴注入:

場(chǎng)景:展示層調(diào)用AccountServiceImpl(業(yè)務(wù)層)的saveAccount方法,這個(gè)方法中又調(diào)用AccountDao(持久層)類的保存賬號(hào)方法,那這個(gè)時(shí)候AccountServiceImpl類中就需要引用到AccountDao對(duì)象,我們前面已經(jīng)把這兩個(gè)對(duì)象都用spring創(chuàng)建出來(lái)了,那么現(xiàn)在開(kāi)始往AccountServiceImpl中依賴AccountDao對(duì)象,為了簡(jiǎn)單我們先用簡(jiǎn)單類型的屬性代替AccountDao對(duì)象引入到AccountServiceImpl中:

1、構(gòu)造函數(shù)注入:
使用constructor-arg標(biāo)簽,該標(biāo)簽是寫在bean標(biāo)簽內(nèi)部的子標(biāo)簽:
    標(biāo)簽的屬性:
        type:指定要注入的參數(shù)在構(gòu)造函數(shù)中的類型
        index:指定要注入的參數(shù)在構(gòu)造函數(shù)中的索引位置
        name:指定要注入的參數(shù)在構(gòu)造函數(shù)中的名稱
        value:指定要注入數(shù)據(jù)內(nèi)容,他只能指定基本類型數(shù)據(jù)和String類型數(shù)據(jù)
        ref:指定其他bean類型數(shù)據(jù)。寫的是其他bean的id。其他bean指的是存在于spring容器中的bean。
例子:
<bean id=“accountService” class=“com.demo.service.impl.AccountServiceImpl”>
    <constructor-arg    name=“name”  value=“xc”></constructor-org>
    <constructor-arg    name=“age”  value=“27”></constructor-org>
    <constructor-arg    name=“birthday”  ref=“now”></constructor-org>
<bean/>
<bean id=“now” class=“java.util.Date”></bean>

這種方式需要AccountServiceImpl類中有帶有這三個(gè)參數(shù)的構(gòu)造函數(shù),否則報(bào)錯(cuò)。
這時(shí)候在展示層通過(guò)spring獲取的AccountServiceImpl對(duì)象其中的三個(gè)屬性就已經(jīng)有了上面設(shè)置的值,這感覺(jué)有點(diǎn)像是初始化對(duì)象賦值呢?不過(guò)好像確實(shí)是這樣,因?yàn)槭怯脴?gòu)造函數(shù)注入的。

2、使用setter方法注入:(常用)
涉及的標(biāo)簽:property。也是要寫在bean標(biāo)簽內(nèi)部的子標(biāo)簽
標(biāo)簽屬性:
    name:指定的是setter方法的名稱。匹配的是類中setter方法set后面的部分:setAppName(),那么這里就取appName,首字母要小寫。
    value:指定要注入數(shù)據(jù)內(nèi)容,他只能指定基本類型數(shù)據(jù)和String類型數(shù)據(jù)
    ref:指定其他bean類型數(shù)據(jù)。寫的是其他bean的id。其他bean指的是存在于spring容器中的bean。
    例子:
    <bean id=“accountService” class=“com.demo.service.impl.AccountServiceImpl”>
    <property    name=“name”  value=“xc”></property>
    <property    name=“age”  value=“27”></property>
    <property    name=“birthday”  ref=“now”></property>
    <bean/>

這種方式需要類中的屬性有set方法,可以沒(méi)有g(shù)et方法,但是一定要有set方法.
用這種方式往AccountServiceImpl中引用AccountDao:

<bean id=“accountService” class=“com.demo.service.impl.AccountServiceImpl”>
<property name=“accountDao” ref=“accountDao”></constructor-org>
<bean/>
<bean id=“accountDao” class=“com.demo.dao.impl.AccountDaoImpl”><bean/>
這樣寫完,業(yè)務(wù)層和持久層的依賴關(guān)系就交給了spring來(lái)維護(hù)了。

  • 2.1使用p名稱空間注入:它的本質(zhì)仍然是需要類中提供set方法,同時(shí)在配置文件中要導(dǎo)入p名稱空間:

<bean id=“accountService” class=“com.demo.service.impl.AccountServiceImpl” p:name=“張三”>
<bean/>

  • 2.2復(fù)雜類型注入:注入的方式采用set方法,注入的類型都是集合類型:
    注意:結(jié)構(gòu)相同標(biāo)簽可以互換
          <!— 給數(shù)組注入數(shù)據(jù)—>
          <property    name=“myStrs” >
              <array>
                  <value>AAA</value>
                  <value>BBB</value>
                  <value>ccc</value>
              </array>
          </property>
          <!— 給list注入數(shù)據(jù)—>
          <property    name=“myList” >
              <list>
                  <value>AAA</value>
                  <value>BBB</value>
                  <value>ccc</value>
              </list>
          </property>
          <!— 給set注入數(shù)據(jù)—>
          <property    name=“mySet” >
              <set>
                  <value>AAA</value>
                  <value>BBB</value>
                  <value>ccc</value>
              </set>
          </property>
          <!— 給map注入數(shù)據(jù)—>
          <property    name=“myMap” >
              <map>
                  <entry key=“testA” value=“AAA”></value>
                  <entry key=“testB” value=“BBB”></value>
              </map>
          </property>
          <!— 給properties注入數(shù)據(jù)—>
          <property    name=“myProps” >
              <props>
                  <prop key=“testa”>AAA</value>
                  <prop key=“testB”>BBB</value>
              </props>
          </property>
      <bean/>
    
    
1.3用spring注解的方式再做一遍上面的工作:

和上面xml的目的都是為了降低耦合,只不過(guò)是形式不一樣

 * 用于創(chuàng)建對(duì)象的:
 *
 * @Component :
 * 作用:就相當(dāng)于在spring的xml配置文件中寫了一個(gè)bean標(biāo)簽。
 * 屬性:
 * value:用于指定bean的Id。當(dāng)不寫時(shí),默認(rèn)值是當(dāng)前類名,首字母改小寫。
 * 由此注解衍生的三個(gè)注解:
 * @Controller, 用于表現(xiàn)層
 * @Service, 用于業(yè)務(wù)層
 * @Repository 用于持久層
 * 他們的作用以及屬性和@Component的作用是一樣的。它們的出現(xiàn)時(shí)spring框架為我們提供更明確的語(yǔ)義話來(lái)指定不同層的bean對(duì)象。
 * <p>
 * 用于注入數(shù)據(jù)的:
 * @Autowired
 * 作用:自動(dòng)按照類型注入。只要容器中有唯一的類型匹配,則可以直接注入成功。
 * 細(xì)節(jié):當(dāng)使用此注解注入時(shí),set方法就可以省略了。
 * 屬性:required :是否必須注入成功。取值true(默認(rèn)值)/false。當(dāng)取值是true時(shí),沒(méi)有匹配的對(duì)象就會(huì)報(bào)錯(cuò)。寫不寫無(wú)所謂,反正沒(méi)有匹配到總會(huì)報(bào)錯(cuò),只不過(guò)報(bào)錯(cuò)信息不一樣。
 * 用于改變作用范圍的:
 * 和生命周期相關(guān)的:
 */

@Component(value = "accountService")
public class AccountServiceImpl implements IAccountService {

    @Autowired(required = false)
    IAccountDao accountDao;

    @Override
    public void saveAccount() {
        accountDao.saveAccount();
    }
}

public class Client {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService accountService = ac.getBean("accountService",IAccountService.class);
        IAccountDao accountDao = ac.getBean("accountDao",IAccountDao.class);

        accountService.saveAccount();
    }
}
<?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-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!--告知spring創(chuàng)建容器時(shí)要掃描的包-->
    <context:component-scan base-package="com.ncz.nczupkeep.biz"></context:component-scan>

</beans>


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 175,553評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,620評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評(píng)論 6 405
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 54,940評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,170評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,407評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,663評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評(píng)論 2 370

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

  • 來(lái)源:關(guān)于Spring IOC (DI-依賴注入)你需要知道的一切作者:zejian Dao層(AccountDa...
    楊井閱讀 5,348評(píng)論 0 27
  • 前言 只有光頭才能變強(qiáng) 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡(jiǎn)單啦 單例模式你會(huì)幾種寫法? 工...
    Java3y閱讀 2,288評(píng)論 1 60
  • 1.Spring簡(jiǎn)介 Spring是J2EE開(kāi)發(fā)中一個(gè)很重要的框架。它主要用來(lái)解決下面兩個(gè)問(wèn)題。 解決大型軟件開(kāi)發(fā)...
    sixleaves閱讀 1,379評(píng)論 0 6
  • Spring容器高層視圖 Spring 啟動(dòng)時(shí)讀取應(yīng)用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof閱讀 2,829評(píng)論 1 24
  • 定義: 控制反轉(zhuǎn)(Inversion Of Control):獲得依賴對(duì)象的過(guò)程被反轉(zhuǎn)了,由自身的管理,變成IOC...
    一凡呀閱讀 2,159評(píng)論 0 8