Spring IoC容器和bean

IoC容器是spring框架的核心組件骤素,spring通過IoC容器來管理所有Java對象及其相互間的依賴關(guān)系。

依賴注入(Dependency Injection,DI)和控制反轉(zhuǎn)的關(guān)系:

兩者其實是一個事物的兩種不同說法梦谜,本質(zhì)上是一回事。依賴注入是一個程序設(shè)計模式和架構(gòu)模型,也稱控制反轉(zhuǎn)碍现。在技術(shù)上來說依賴注入是一個控制反轉(zhuǎn)的特殊事項躏升,但依賴注入還指一個對象應(yīng)用另外一個對象來提供一個特殊的能力一睁。如把一個數(shù)據(jù)庫連接以參數(shù)的形式傳到一個對象的結(jié)構(gòu)方法里饲帅,而不是在那個對象內(nèi)部自行創(chuàng)建一個連接。

依賴注入和控制反轉(zhuǎn)的基本思想是把類的依賴從類內(nèi)部轉(zhuǎn)到外部以減少依賴。利用控制反轉(zhuǎn)按声,對象在被創(chuàng)建時渐裂,會由一個調(diào)控系統(tǒng)統(tǒng)一進行對象實例的隔離哈垢,將該對象鎖依賴對象的引用通過調(diào)控系統(tǒng)傳遞給它绑警,或者說被注入到對象中。控制反轉(zhuǎn)是關(guān)于一個對象如何獲取它所依賴對象的引用的過程,這個過程體現(xiàn)為”誰來傳遞依賴的引用“這個職責的反轉(zhuǎn)。

控制反轉(zhuǎn)的實現(xiàn)類型:依賴注入(Dependency Injection埋心,DI)和依賴查找(Dependency Lookup)晨横。其中依賴注入應(yīng)用較為廣泛手形,spring就是采用此方式來實現(xiàn)控制反轉(zhuǎn)的啥供。

IoC容器和bean概述

Spring通過IoC容器來管理所有Java對象及其之間的依賴關(guān)系伙狐。IoC解決了各個對象之間不需要直接關(guān)聯(lián)罢防,而在需要時由IoC容器來管理對象的依賴關(guān)系,開發(fā)者只需維護相對獨立的各個對象代碼即可硅确。

IoC是一個過程明肮,即對象定義及其依賴關(guān)系疏魏,其他與之配合的對象只能通過構(gòu)造函數(shù)、工廠方法參數(shù)官份、從工廠方法構(gòu)造或返回或在對象實例上設(shè)置的屬性來定義依賴關(guān)系只厘,然后IoC容器在創(chuàng)建bean時會注入這些依賴項。此過程在職責上是反轉(zhuǎn)的舅巷,即先把原來代碼中需要實現(xiàn)的對象創(chuàng)建羔味、依賴的代碼反轉(zhuǎn)給容器來實現(xiàn)和管理,故稱為控制反轉(zhuǎn)钠右。

IoC的應(yīng)用的設(shè)計模式:

1)反射:在程序運行狀態(tài)中根據(jù)提供的類路徑或類名赋元,通過反射來動態(tài)獲取該類所有的屬性及方法。

2)工廠模式:把IoC容器當做一個工廠飒房,在配置文件或注解中給出定義搁凸,然后利用反射技術(shù),根據(jù)給出的類名生成相應(yīng)的對象狠毯。對象生成的代碼和對象之間的依賴關(guān)系在配置?文件中定義护糖,以此實現(xiàn)解耦。

org.springframework.beans和org.springframework.context包是IoC容器的基礎(chǔ)嚼松,BeanFactory接口提供了能夠管理任何類型對象的高級配置機制嫡良,ApplicationContext是BeanFactory的子接口锰扶,它更易與AOP功能集成,進行消息資源處理寝受、事件發(fā)布坷牛、作為應(yīng)用層特定的上下文。

bean是由spring?IoC容器進行實例化很澄、組裝并管理的對象漓帅。它們之間的依賴關(guān)系反映在容器使用的配置元數(shù)據(jù)中。

配置元數(shù)據(jù)(Configuration Metadata)

配置元數(shù)據(jù)描述了spring容器在應(yīng)用程序中是如何提供實例化痴怨、配置和組裝對象的忙干。配置元數(shù)據(jù)的幾種方式:基于XML方式、基于注解浪藻、基于Java的配置捐迫。比較流行的是后兩種。

\bullet 基于注解的配置:從spring2.5開始引入爱葵。

\bullet 基于Java的配置:從spring3.0開始引入施戴。可以使用Java而不是XML文件來定義應(yīng)用程序類外部的bean萌丈。常用的注解有:@Configuration赞哗、@Bean、@Import辆雾、@DependsOn肪笋。

spring配置至少需要一個活多個由容器管理的bean《扔兀基于XML的方式藤乙,需要用到<beans/>元素內(nèi)的<bean/>元素來配置bean,在基于Java的配置中惭墓,通常在@Configuration注解的類中使用@Bean注解的方法坛梁。

XML配置元數(shù)據(jù)的方式

在XML文件中,id屬性用于標識單個bean定義的字符串腊凶,它的值是指協(xié)作對象划咐,class屬性定義bean的類型,使用完全限定的類名钧萍。

基于注解的配置元數(shù)據(jù)方式

實例化容器

spring?IoC容器需要在應(yīng)用啟動時進行實例化褐缠,在實例化過程中,IoC容器會從外部資源加載配置元數(shù)據(jù)划煮,提供給ApplicationContext構(gòu)造函數(shù)送丰。

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"service.xml","dao.xml"}); //從類路徑中加載基于XML的配置元數(shù)據(jù)

當系統(tǒng)較大時缔俄,通常會將bean定義分到多個XML中弛秋,這樣每個XML配置文件可以表示系統(tǒng)中的邏輯層或模塊器躏。當某個構(gòu)造函數(shù)需要多個資源位置時,可以使用一個或多個<import/>從另外一個文件加載bean的定義蟹略。

使用一個或多個<import/>?引入bean?

使用容器

ApplicationContext是高級工廠的接口登失,可以維護不同的bean及其依賴項的注冊表。其中<T> T getBean(String var1, Class<T> var2)方法可以用于搜索bean實例挖炬。

用getBean()方法獲取bean實例

正常情況下應(yīng)用程序不應(yīng)該使用ApplicationContext中的方法揽浙,因為程序代碼不需要調(diào)用getBean方法,就可以完全不依賴于spring API意敛。如spring與web框架集成馅巷,為各種web框架提供了依賴注入,它允許開發(fā)者通過元數(shù)據(jù)聲明對特定bean的依賴關(guān)系草姻。

bean的命名

每個bean都有一個或多個標識符钓猬,這些標識符在托管bean的容器中必須是唯一的。一個bean一般只有一個標識符撩独,如果需要多個標識符敞曹,額外的標識符會被當作是別名。

在基于XML的配置元數(shù)據(jù)中综膀,使用id或name屬性來指定bean標識符澳迫。id屬性允許指定一個id,這些標識符的名稱是字母或者包含特殊字符剧劝。如果向bean引入其他別名橄登,可以在name屬性中指定,用“讥此,”示绊、“;”暂论、空格分隔面褐。在spring3.1之前,id屬性被定義為一個xsd:ID類型取胎,限制了可能的字符展哭。之后的版本被定義為一個xsd:string類型。雖然更改了類型闻蛀,但bean的唯一性仍由容器強制執(zhí)行匪傍。

用戶可以不必為bean提供名稱或標識符,若沒有顯示的提供名稱或標識符觉痛,容器會為其自動生成唯一的名稱役衡。如果想通過名稱引用該bean,就必須提供一個名稱薪棒。

在bean的命名時盡量使用Java規(guī)范手蝎,即bean的名稱要遵循以一個小寫字母開頭的駝峰命名規(guī)則榕莺,如“userDao”、"indexController"棵介、"userService"等钉鸯。spring為未命名的組件生成bean名稱,同樣遵循上述原則邮辽。最簡單的命名方式就是直接采用類名稱并將其首字母改成小寫唠雕,但當前兩個字母都是大寫時可以不進行處理,如“URL”類bean的名稱仍然不變吨述。這些命名規(guī)則定義在java.beans.Introspector.decapitalize方法中岩睁。

decapitalize()定義

實例化bean的方式

bean的實例化就是根據(jù)配置來創(chuàng)建對象的過程,主要有以下三種方式:

\bullet 通過構(gòu)造函數(shù)實例化

Spring IoC容器可以管理所有想讓它管理的類揣云,如POJO笙僚、非bean形式的類等。當使用構(gòu)造方法來創(chuàng)建bean時灵再,對spring來說并無特殊之處肋层。根據(jù)所使用的IoC類型,可能需要一個默認(無參)的構(gòu)造方法翎迁。當使用XML配置方式時栋猖,可如下配置:

<bean id="myBean" class="com.xxx.service.MyBean" />

\bullet 使用靜態(tài)工廠方法實例化

當使用靜態(tài)工廠方法創(chuàng)建bean時,除了指定class屬性外汪榔,還要通過factory-method屬性來指定創(chuàng)建bean實例的工廠方法蒲拉,spring將調(diào)研此方法返回實例對象。其實它和使用普通構(gòu)造器創(chuàng)建實例并無差別痴腌。示例如下:

<bean id="userService" class="com.xxx.service.UserService" />

public class?UserService {

? ? private static?UserService service = new?UserServiceImpl();

? ? private?UserService() {}

? ? public static?UserService createInstance() {return service;}

}

\bullet 使用工廠實例方法實例化

通過調(diào)用工廠實例的非靜態(tài)方法進行實例化雌团,與通過靜態(tài)工廠方法實例化類似,使用時class屬性設(shè)置為空士聪,而factory-method屬性必須指定為當前/祖先容器中包含工廠方法的bean的名稱锦援,而該工廠bean的工廠方法本身須通過factory-method屬性來設(shè)定。示例如下:

<!--?工廠bean剥悟,包含createInstance()方法?-->

<bean id="serviceLocator" class="com.xxx.DefaultServiceLocator" >

? ??<!--?其他需要注入的依賴項 -->

</bean>

<!--?通過工廠bean創(chuàng)建的bean -->

<bean id="userService" factory-bean="serviceLocator"?

????factory-method="createUserServiceInstance" />

<bean id="accountService" factory-bean="serviceLocator"?

????factory-method="createAccountServiceInstance" />


public class?DefaultServiceLocator {

? ??private static?UserService userService = new?UserServiceImpl();

????private static?AccountService accService = new?AccountServiceImpl();

? ? private?DefaultServiceLocator() {}

? ? public?UserService??createUserServiceInstance() {return userService;}

? ? public AccountService??createAccountServiceInstance() {return?accService;}

}


--參考文獻《Srping5開發(fā)大全》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末灵寺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子区岗,更是在濱河造成了極大的恐慌略板,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慈缔,死亡現(xiàn)場離奇詭異叮称,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門瓤檐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赂韵,“玉大人,你說我怎么就攤上這事距帅∮蚁牵” “怎么了括堤?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵碌秸,是天一觀的道長。 經(jīng)常有香客問我悄窃,道長讥电,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任轧抗,我火速辦了婚禮恩敌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘横媚。我一直安慰自己纠炮,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布灯蝴。 她就那樣靜靜地躺著恢口,像睡著了一般。 火紅的嫁衣襯著肌膚如雪穷躁。 梳的紋絲不亂的頭發(fā)上耕肩,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音问潭,去河邊找鬼猿诸。 笑死,一個胖子當著我的面吹牛狡忙,可吹牛的內(nèi)容都是我干的梳虽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼灾茁,長吁一口氣:“原來是場噩夢啊……” “哼怖辆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起删顶,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤竖螃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后逗余,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體特咆,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了腻格。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片画拾。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖菜职,靈堂內(nèi)的尸體忽然破棺而出青抛,到底是詐尸還是另有隱情,我是刑警寧澤酬核,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布蜜另,位于F島的核電站,受9級特大地震影響嫡意,放射性物質(zhì)發(fā)生泄漏举瑰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一蔬螟、第九天 我趴在偏房一處隱蔽的房頂上張望此迅。 院中可真熱鬧,春花似錦旧巾、人聲如沸耸序。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坎怪。三九已至,卻和暖如春绳匀,著一層夾襖步出監(jiān)牢的瞬間芋忿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工疾棵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留戈钢,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓是尔,卻偏偏與公主長得像殉了,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子拟枚,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

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