Spring-Ioc

2019-06-11
? Ioc即Inverse of Control侵贵,中文為控制反轉(zhuǎn)东抹。

? 在Spring中介蛉,創(chuàng)建對(duì)象的工作不再由應(yīng)用程序主動(dòng)完成爆阶,而是由Spring容器負(fù)責(zé)創(chuàng)建燥透,然后注入給應(yīng)用程序,由Spring來(lái)管理應(yīng)用程序中的所有對(duì)象及其依賴關(guān)系扰她。所以控制反轉(zhuǎn)是說(shuō)創(chuàng)建對(duì)象的控制權(quán)進(jìn)行轉(zhuǎn)移,以前創(chuàng)建對(duì)象是由應(yīng)用程序自己把控的芭碍,而現(xiàn)在這種權(quán)力轉(zhuǎn)移交給了Spring容器徒役。

? 應(yīng)用程序在使用了Spring后,就無(wú)需再進(jìn)行對(duì)象的創(chuàng)建工作了窖壕,而是通過(guò)Spring配置文件描述對(duì)象的創(chuàng)建方法忧勿、參數(shù)以及對(duì)象間的依賴關(guān)系。Spring會(huì)自動(dòng)依據(jù)配置文件中對(duì)象之間的依賴關(guān)系運(yùn)用Java的反射技術(shù)創(chuàng)建所需要的對(duì)象瞻讽。

創(chuàng)建對(duì)象

在Spring核心文件中使用<bean>標(biāo)簽創(chuàng)建對(duì)象

<bean id="user" class="com.jevon.model.User">
    <property name="id" value="001"></property>
    <property name="name" value="張三"></property>
    <property name="age" value="20"></property>
</bean>

獲取對(duì)象

ApplicationContext container = new ClassPathXmlApplicationContext("applicationContext.xml");
User obj = container.getBean("user", User.class);
System.out.println(obj.getId());
System.out.println(obj.getName());

Spring Bean的作用域

Bean的作用域就是Bean實(shí)例的生存空間或有效范圍鸳吸。可通過(guò)配置文件中<bean>元素的scope屬性配置速勇。

作用域名稱 功 能 描 述
singleton 單實(shí)例作用域晌砾,這是Spring容器默認(rèn)的作用域。使用singleton作用域生成的是單實(shí)例烦磁,在整個(gè)Bean容器中僅保留一個(gè)實(shí)例對(duì)象供所有調(diào)用者共享引用养匈。Spring容器負(fù)責(zé)跟蹤Bean實(shí)例的狀態(tài),負(fù)責(zé)維護(hù)Bean實(shí)例的生命周期行為都伪。單例模式對(duì)于那些無(wú)會(huì)話狀態(tài)的Bean(如輔助工具類呕乎、DAO組件、業(yè)務(wù)邏輯組件等)是最理想的選擇陨晶。 注意:Spring通過(guò)AOP與LocalThread功能解決了DAO中Connection的非線程安全問(wèn)題猬仁。
prototype 原型模式,這是多實(shí)例作用域先誉,每次從容器中獲取Bean時(shí)湿刽,都會(huì)創(chuàng)建一個(gè)新的實(shí)例以供調(diào)用者使用。prototype作用域非常適用于那些需要保持會(huì)話狀態(tài)的Bean實(shí)例褐耳,但其內(nèi)存開(kāi)銷(xiāo)太大叭爱。 有一點(diǎn)值得注意的就是,Spring不能對(duì)一個(gè)prototype Bean的整個(gè)生命周期負(fù)責(zé)漱病,容器在初始化买雾、裝配好一個(gè)prototype實(shí)例后把曼,將它交給客戶端,隨后就對(duì)該prototype實(shí)例不聞不問(wèn)了漓穿。因此嗤军,客戶端要負(fù)責(zé)prototype實(shí)例的生命周期管理。
request 針對(duì)每次HTTP請(qǐng)求晃危,Spring容器會(huì)根據(jù)Bean的定義創(chuàng)建一個(gè)全新的Bean實(shí)例叙赚, 且該Bean實(shí)例僅在當(dāng)前HTTP request內(nèi)有效,因此可以根據(jù)需要放心地更改所建實(shí)例的內(nèi)部狀態(tài)僚饭, 而其他請(qǐng)求中根據(jù)Bean定義創(chuàng)建的實(shí)例震叮,將不會(huì)看到這些特定于某個(gè)請(qǐng)求的狀態(tài)變化。 當(dāng)處理請(qǐng)求結(jié)束鳍鸵,request作用域的Bean實(shí)例將被銷(xiāo)毀苇瓣。該作用域僅在基于web的Spring ApplicationContext情形下有效。
session 針對(duì)某個(gè)HTTP Session偿乖,Spring容器會(huì)根據(jù)Bean定義創(chuàng)建一個(gè)全新的Bean實(shí)例击罪,且該Bean實(shí)例僅在當(dāng)前HTTP Session內(nèi)有效。 與request作用域一樣贪薪,我們可以根據(jù)需要放心地更改所創(chuàng)建實(shí)例的內(nèi)部狀態(tài)媳禁,而別的HTTP Session中根據(jù)Bean定義創(chuàng)建的實(shí)例, 將不會(huì)看到這些特定于某個(gè)HTTP Session的狀態(tài)變化画切。 當(dāng)HTTP Session最終被廢棄的時(shí)候竣稽,在該HTTP Session作用域內(nèi)的Bean實(shí)例也會(huì)被廢棄掉。該作用域僅在基于Web的Spring ApplicationContext情形下有效霍弹。
global session global session作用域類似于標(biāo)準(zhǔn)的HTTP Session作用域丧枪,不過(guò)它僅僅在基于portlet的Web應(yīng)用中才有意義。portlet規(guī)范定義了全局Session的概念庞萍,它被所有構(gòu)成某個(gè)portlet Web應(yīng)用的各種不同的portlet所共享拧烦。在global session作用域中定義的Bean被限定于全局portlet Session的生命周期范圍內(nèi)。如果我們是在編寫(xiě)一個(gè)標(biāo)準(zhǔn)的基于Servlet的Web應(yīng)用钝计,并且定義了一個(gè)或多個(gè)具有g(shù)lobal session作用域的Bean恋博,系統(tǒng)會(huì)使用標(biāo)準(zhǔn)的HTTP Session作用域,并且不會(huì)引起任何錯(cuò)誤私恬。該作用域僅在基于Web的Spring ApplicationContext情形下有效债沮。

當(dāng)系統(tǒng)創(chuàng)建Spring容器時(shí),默認(rèn)會(huì)預(yù)初始化所有的singleton Bean本鸣。即容器初始化完成后疫衩,容器中所有的singleton Bean也實(shí)例化完成。這意味著系統(tǒng)前期初始化時(shí)將有較大的開(kāi)銷(xiāo)荣德,但一旦初始化完成闷煤,程序后面獲取singleton Bean實(shí)例時(shí)將擁有較好性能童芹。

可以通過(guò)指定<bean>元素中的lazy-init屬性來(lái)延遲初始化Bean,這樣將會(huì)在第一次獲取Bean的時(shí)候初始化Bean鲤拿。

<bean id="" class="" lazy-init="true"/>  

如果想對(duì)所有的Bean都延遲初始化假褪,可以修改<beans>元素

<beans lazy-init="true">

ApplicationContext接口的常用方法

boolean containsBean(String name)
判斷IoC容器是否包含id為name的Bean實(shí)例。
Class<?> getType(String name)
返回容器中指定Bean實(shí)例的類型近顷。
Boolean isSingleton(String)
判斷給定名稱的Bean實(shí)例是否為單例(Singleton)模式生音。
T getBean(Class<T> requiredType)
獲取IoC容器中屬于requiredType類型的、唯一的Bean實(shí)例窒升。
Object getBean(String name)
返回容器id為name的Bean實(shí)例缀遍。
T getBean(String name,Class requiredType)
返回容器中id為name,但在返回之前會(huì)進(jìn)行類型檢查饱须。如果不能轉(zhuǎn)換成requiredType類型域醇,則會(huì)拋出異常。

Spring DI配置

DI即依賴注入冤寿,是Ioc思想的具體體現(xiàn)歹苦,表示對(duì)象之間的依賴關(guān)系由Spring管理青伤,應(yīng)用程序在運(yùn)行時(shí)由Spring容器動(dòng)態(tài)地將對(duì)象的依賴關(guān)系裝配好督怜,而不是由應(yīng)用程序手動(dòng)裝配。

基于setter方法的依賴注入

<!-- 注冊(cè)一個(gè)Country實(shí)例名稱為country --> 
<bean id="country" class="com.model.Country">
    <property name="id" value="101"/>
    <property name="name" value="中華人民共和國(guó)"/>
</bean>

<!-- 注冊(cè)一個(gè)User實(shí)例名稱為user -->  
<bean id="user" class="com.model.User">  
    <property name="id" value="0001" />
    <property name="name" value="張三" />
    <property name="password" value="123456" />
    <property name="country" ref="country" /><!-- 引用country實(shí)例 -->
</bean>

基于構(gòu)造器的依賴注入

通過(guò)調(diào)用帶參數(shù)的構(gòu)造器實(shí)現(xiàn)狠角。配置<constructor-arg>元素時(shí)可指定index屬性号杠,用于指定該構(gòu)造參數(shù)將作為第幾個(gè)構(gòu)造參數(shù)值。如index="0"表明該構(gòu)造參數(shù)值將作為第一個(gè)構(gòu)造參數(shù)丰歌∫腆可以通過(guò)type屬性指定參數(shù)類型,以避免出現(xiàn)構(gòu)造器重載的匹配問(wèn)題立帖。

<!-- 注冊(cè)一個(gè)Country實(shí)例名稱為country --> 
<bean id="country" class="com.model.Country">
    <property name="id" value="101"/>
    <property name="name" value="中華人民共和國(guó)"/>
</bean>
    
<!-- 注冊(cè)一個(gè)User實(shí)例名稱為user -->  
<bean id="user" class="com.model.User">  
    <constructor-arg value="0001" type="String" />
    <constructor-arg value="張三" type="String" />
    <constructor-arg value="123456" type="String" />
    <constructor-arg ref="country" type="com.model.Country" />
</bean>

集合屬性注入

可以使用<list>眼溶、<set>、<map>晓勇、<array>標(biāo)簽分別用來(lái)設(shè)置類型為L(zhǎng)ist堂飞、Set、Map绑咱、數(shù)組的屬性值绰筛。

主要參數(shù):

  • value:指定集合元素值是基本數(shù)據(jù)類型值或字符串類型值
  • ref:指定集合元素值是容器中另一個(gè)Bean實(shí)例
  • bean:指定集合元素值是一個(gè)嵌套Bean
public class User {
    private String id;// ID號(hào)
    private String name; // 用戶名
    private String password;// 密碼
    private List<String> friends; // 好友列表
    private Set<Account> accounts;// 賬戶列表
}
<bean id="account" class="com.model.Account" scope="prototype">
    <property name="id" value="0001" />
    <property name="password" value="111111" />
    <property name="balance" value="1000" />
</bean>

<!-- 注冊(cè)一個(gè)User實(shí)例名稱為user -->  
<bean id="user" class="com.model.User">  
    <property name="id" value="1000" />
    <property name="name" value="張三" />
    <property name="password" value="123456" />
    <property name="friends">
        <list>
            <value>"李四"</value>
            <value>"王五"</value>
            <value>"趙六"</value>
        </list>
    </property>
    <property name="accounts">
        <set>
            <ref bean="account" />
            <bean class="com.model.Account">
                <property name="id" value="0002" />
                <property name="password" value="222222" />
                <property name="balance" value="2000"/>
            </bean>
        </set>
    </property>
</bean>

分層開(kāi)發(fā)依賴注入

<!-- 注冊(cè)UserDaoImpl實(shí)例userDao -->  
<bean id="userDao" class="com.dao.impl.UserDaoImpl" />  

<!-- 注冊(cè)UserServiceImpl實(shí)例userService -->  
<bean id="userService" class="com.service.impl.UserServiceImpl">  
    <!--調(diào)用set方法,將UserDaoImpl實(shí)例userDao注入給UserServiceImpl實(shí)例的userDao屬性-->  
    <property name="userDao" ref="userDao"/>  
</bean>  

<!-- 注冊(cè)LoginController實(shí)例名稱為loginController -->  
<bean id="loginController" class="com.controller.LoginController">  
    <!--調(diào)用set方法描融,將UserServiceImpl實(shí)例userService注入給LoginController實(shí)例的userService屬性-->  
    <property name="userService" ref="userService" />  
</bean> 

自動(dòng)裝配

Spring IoC容器可以使用自動(dòng)裝配(autowire)管理Bean之間的依賴關(guān)系铝噩,以減少配置量。
自動(dòng)裝配方式可以通過(guò)<bean>元素的autowire屬性指定, 取值如下:

  • no:不使用自動(dòng)裝配窿克,默認(rèn)值骏庸。需要通過(guò)ref屬性進(jìn)行依賴關(guān)系的指定毛甲。在較大的部署環(huán)境中不鼓勵(lì)改變這個(gè)配置,顯式配置能夠得到清晰的依賴關(guān)系敞恋。
  • byName:根據(jù)屬性名自動(dòng)裝配丽啡。查找id值與屬性名完全一致的Bean,并將其與屬性自動(dòng)裝配硬猫。
  • byType:如果容器中存在一個(gè)與指定屬性類型相同的Bean补箍,那么將與該屬性自動(dòng)裝配。如果存在多個(gè)該類型的Bean啸蜜,那么將會(huì)拋出異常坑雅。

方法一:給bean元素設(shè)置autowire屬性

<bean id="" class="" autowire="byName" /> 

方法二:設(shè)置beans全局自動(dòng)裝配

<beans default-autowire="byName">

基于注解的Ioc實(shí)現(xiàn)

Spring提供了完全基于注解配置Bean、裝配Bean的功能衬横,用于替換原來(lái)基于XML的配置方法裹粤,減少配置量。

首先要在配置文件中啟用注解掃描:

<context:component-scan base-package="com"/>

<context:component-scan />標(biāo)簽負(fù)責(zé)掃描哪些類有注解蜂林,如果掃描到有注解的類遥诉,則將其注冊(cè)為bean,并將bean的名字設(shè)置為該類的類名噪叙,但首字母小寫(xiě)矮锈。base-package為需要掃描的包路徑(含所有子包)。

常用Spring注解:

  • @Controller:用于標(biāo)注控制器組件
  • @Service:用于標(biāo)注業(yè)務(wù)層組件
  • @Repository:用于標(biāo)注數(shù)據(jù)訪問(wèn)組件
  • @Component:用于對(duì)比較中立的類進(jìn)行注解睁蕾。與前三個(gè)注解等效苞笨。
  • @Resource:用于依賴關(guān)系裝配。默認(rèn)按名稱裝配子眶。名稱可以通過(guò)@Resource的name屬性指定瀑凝。如果沒(méi)有指定name屬性,則支持自動(dòng)裝配臭杰。
  • @Autowired:自動(dòng)裝配
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末粤咪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子渴杆,更是在濱河造成了極大的恐慌寥枝,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件将塑,死亡現(xiàn)場(chǎng)離奇詭異脉顿,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)点寥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)艾疟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事蔽莱〉芙” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵盗冷,是天一觀的道長(zhǎng)怠苔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)仪糖,這世上最難降的妖魔是什么柑司? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮锅劝,結(jié)果婚禮上攒驰,老公的妹妹穿的比我還像新娘。我一直安慰自己故爵,他們只是感情好玻粪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著诬垂,像睡著了一般劲室。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上结窘,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天很洋,我揣著相機(jī)與錄音,去河邊找鬼晦鞋。 笑死蹲缠,一個(gè)胖子當(dāng)著我的面吹牛棺克,可吹牛的內(nèi)容都是我干的悠垛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼娜谊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼确买!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起纱皆,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤湾趾,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后派草,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體搀缠,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年近迁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了艺普。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖歧譬,靈堂內(nèi)的尸體忽然破棺而出岸浑,到底是詐尸還是另有隱情,我是刑警寧澤瑰步,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布矢洲,位于F島的核電站,受9級(jí)特大地震影響缩焦,放射性物質(zhì)發(fā)生泄漏读虏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一袁滥、第九天 我趴在偏房一處隱蔽的房頂上張望掘譬。 院中可真熱鬧,春花似錦呻拌、人聲如沸葱轩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)靴拱。三九已至,卻和暖如春猾普,著一層夾襖步出監(jiān)牢的瞬間袜炕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工初家, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留偎窘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓溜在,卻偏偏與公主長(zhǎng)得像陌知,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掖肋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

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

  • 來(lái)源:關(guān)于Spring IOC (DI-依賴注入)你需要知道的一切作者:zejian Dao層(AccountDa...
    楊井閱讀 5,333評(píng)論 0 27
  • 前言 只有光頭才能變強(qiáng) 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡(jiǎn)單啦 單例模式你會(huì)幾種寫(xiě)法志笼? 工...
    Java3y閱讀 2,284評(píng)論 1 60
  • Spring容器高層視圖 Spring 啟動(dòng)時(shí)讀取應(yīng)用程序提供的Bean配置信息沿盅,并在Spring容器中生成一份相...
    Theriseof閱讀 2,812評(píng)論 1 24
  • 1.Spring簡(jiǎn)介 Spring是J2EE開(kāi)發(fā)中一個(gè)很重要的框架。它主要用來(lái)解決下面兩個(gè)問(wèn)題纫溃。 解決大型軟件開(kāi)發(fā)...
    sixleaves閱讀 1,369評(píng)論 0 6
  • 全注解下的 Spring IoC 本文基于 Spring Boot腰涧,所以并不使用 XML 配置,使用注解描述生成對(duì)...
    igeeks閱讀 1,286評(píng)論 0 12