Java程序员从笨鸟到菜鸟之(七十)细谈Spring(三)IOC和spring基本配置详解
對(duì)于IoC?的一些知識(shí)點(diǎn),相信大家都知道他在spring框架中所占有的地位,應(yīng)該可以算的上是核心之一吧,所以IOC是否理解清楚,決定了大家對(duì)Spring整個(gè)框架的理解?
Ioc的理解
spring?的兩個(gè)核心概念:一個(gè)是控制反轉(zhuǎn)IoC,也可以叫做依賴注入DI。還有一個(gè)是面向切面編程AOP。
控制反轉(zhuǎn):當(dāng)某個(gè)Java?對(duì)象需要(依賴)另一個(gè)java?對(duì)象時(shí),不
是自身直接創(chuàng)建依賴對(duì)象,而是由實(shí)現(xiàn)IoC?的容器(如spring?框架的IoC容器)來創(chuàng)建,并將它注入需要這個(gè)依賴對(duì)象的java?對(duì)象中。
spring?的容器
spring?管理的基本單元是Bean,在spring?的應(yīng)用中,所有的組件都是一個(gè)個(gè)的Bean,它可以是任何的java?對(duì)象。spring?負(fù)責(zé)創(chuàng)建這些Bean的實(shí)例。并管理生命周期。而spring?框架是通過其內(nèi)置的容器來完成Bean?的管理的,Bean?在spring?的容器中生存著,使用時(shí)只需要通過它提供的一些方法從其中獲取即可。
spring?的容器有兩個(gè)接口:BeanFactory?和ApplicationContext?這兩個(gè)接口的實(shí)例被陳為spring?的上下文。
[java]?view plaincopy print?
注:由于ApplicationContext是基于BeanFactory之上的,所以,一般ApplicationContext功能比較強(qiáng)大,建議使用
ApplicationContext經(jīng)常用到的三個(gè)實(shí)現(xiàn):
1.ClassPathXmlApplicationContext:從類路徑中的XML文件載入上下文定義信息。把上下文定義文件當(dāng)成類路徑資源。
2.FileSystemXmlApplicationContext:從文件系統(tǒng)中的XML文件載入上下文定義信息。
3.XmlWebApplicationContext:從Web系統(tǒng)中的XML文件載入上下文定義信息。
?
一:spring?的依賴注入
1)、構(gòu)造器注入
[html]?view plaincopy print?
注:這種注入方式很少用,如果是注入對(duì)象一般為上例注入,但有時(shí)要注入基本數(shù)據(jù)類型,一般用下面方法注入
[html]?view plaincopy print?
如果構(gòu)造方法不只一個(gè)參數(shù)時(shí),應(yīng)指明所注入?yún)?shù)的索引或者數(shù)據(jù)類型,例如:
[html]?view plaincopy print?
2)、設(shè)值(set?方法)注入
[html]?view plaincopy print?
注:<property?name="accountDaoImpl"?ref="accoutDaoImpl"/>
相當(dāng)于調(diào)用set?AccountDaoImpl方法,把值設(shè)為accoutDaoImpl
3)接口注入(很少用)
二:?xml?裝配Bean屬性含義
1.id:指定該Bean?的唯一標(biāo)識(shí)。
2.class:指定該Bean?的全限定名。
3.name:為該Bean?指定一到多個(gè)別名。多個(gè)別名可以用“,”和“;”分割。
4.autowire:指定該Bean?的屬性的裝配方式。
所謂自動(dòng)裝配是指在<BEAN>標(biāo)簽中不用指定其依賴的BEAN,而是通過配置的自動(dòng)裝配來自動(dòng)注入依賴的BEAN,這種做法讓我們的配置更加簡(jiǎn)單
1)no:不使用自動(dòng)裝配。必須通過ref?元素指定依賴,這是默認(rèn)設(shè)置。由于顯式指定協(xié)作者可以使配置更靈活、更清晰,因此對(duì)于較大的部署配置,推薦采用該設(shè)置。而且在某種程度上,它也是系統(tǒng)架構(gòu)的一種文檔形式。
[html]?view plaincopy print?
備注:有property?屬性指定ref
2)byName:根據(jù)屬性名自動(dòng)裝配。此選項(xiàng)將檢查容器并根據(jù)
名字查找與屬性完全一致的bean,并將其與屬性自動(dòng)裝配。例如,在
bean?定義中將autowire?設(shè)置為by?name,而該bean?包含master?屬性(同時(shí)提供setMaster(..)方法),Spring?就會(huì)查找名為master?的bean?定義,并用它來裝配給master?屬性。
<bean?id="bean1"?class="cn.csdn.service.Bean1"
scope="singleton"?autowire="byName"/>
備注:沒有property?屬性
3)byType:如果容器中存在一個(gè)與指定屬性類型相同的
bean,那么將與該屬性自動(dòng)裝配。如果存在多個(gè)該類型的bean,那么
將會(huì)拋出異常,并指出不能使用byType?方式進(jìn)行自動(dòng)裝配。若沒有找到相匹配的bean,則什么事都不發(fā)生,屬性也不會(huì)被設(shè)置。如果你不希望這樣,那么可以通過設(shè)置dependency-check="objects"讓Spring?拋出異常。
備注:spring3.0?以上不拋異常。
<bean?id="bean1"?class="cn.csdn.service.Bean1"
scope="singleton"?autowire="byType"/>
備注:沒有property?屬性
4)Constructor:與byType?的方式類似,不同之處在于它應(yīng)用
于構(gòu)造器參數(shù)。如果在容器中沒有找到與構(gòu)造器參數(shù)類型一致的bean,那么將會(huì)拋出異常。
<bean?id="bean1"?class="cn.csdn.service.Bean1"
scope="singleton"autowire="constructor"/>
備注:沒有property?屬性
5)autodetect:通過bean?類的自省機(jī)制(introspection)來決定是使用constructor?還是byType?方式進(jìn)行自動(dòng)裝配。如果發(fā)現(xiàn)默認(rèn)的
構(gòu)造器,那么將使用byType?方式。
<bean?id="bean1"?class="cn.csdn.service.Bean1"
scope="singleton"?autowire="autodetect"/>
5.scope:指定該Bean?的生存范圍
scope用來聲明IOC容器中的對(duì)象應(yīng)該處的限定場(chǎng)景或者說該對(duì)象的存活空間,即在IOC容器在對(duì)象進(jìn)入相應(yīng)的scope之前,生成并裝配這些對(duì)象,在該對(duì)象不再處于這些scope的限定之后,容器通常會(huì)銷毀這些對(duì)象。
1)?singleton類型的bean定義,在一個(gè)容器中只存在一個(gè)實(shí)例,所有對(duì)該類型bean的依賴都引用這一單一實(shí)例
2)?scope為prototype的bean,容器在接受到該類型的對(duì)象的請(qǐng)求的時(shí)候,會(huì)每次都重新生成一?個(gè)新的對(duì)象給請(qǐng)求方,雖然這種類型的對(duì)象的實(shí)例化以及屬性設(shè)置等工作都是由容器負(fù)責(zé)的,但是只要準(zhǔn)備完畢,并且對(duì)象實(shí)例返回給請(qǐng)求方之后,容器就不在擁有?當(dāng)前對(duì)象的引用,請(qǐng)求方需要自己負(fù)責(zé)當(dāng)前對(duì)象后繼生命周期的管理工作,包括該對(duì)象的銷毀
3)?request?,session和global?session
這三個(gè)類型是spring2.0之后新增的,他們只適用于web程序,通常是和XmlWebApplicationContext共同使用
request:
<bean?id?="requestPrecessor"?class="...RequestPrecessor"???scope="request"?/>
Spring容器,即XmlWebApplicationContext?會(huì)為每個(gè)HTTP請(qǐng)求創(chuàng)建一個(gè)全新的RequestPrecessor對(duì)象,當(dāng)請(qǐng)求結(jié)束后,,該對(duì)象的生命周期即告結(jié)束
session
<bean?id?="userPreferences"?class="...UserPreferences"???scope="session"?/>
Spring容器會(huì)為每個(gè)獨(dú)立的session創(chuàng)建屬于自己的全新的UserPreferences實(shí)例,他比request?scope的bean會(huì)存活更長(zhǎng)的時(shí)間,其他的方面真是沒什么區(qū)別。
global?session:
<bean?id?="userPreferences"?class="...UserPreferences"???scope="globalsession"?/>?
global?session只有應(yīng)用在基于porlet的web應(yīng)用程序中才有意義,他映射到porlet的global范圍的session,如果普通的servlet的web?應(yīng)用中使用了這個(gè)scope,容器會(huì)把它作為普通的session的scope對(duì)待。
6.init-method:指定該Bean?的初始化方法。destroy-method:指定該Bean?的銷毀方法。這個(gè)就像servlet中init和destroy方法一樣,只不過這里在配置文件配置的
7.abstract:指定該Bean?是否為抽象的。如果是抽象的,則
spring?不為它創(chuàng)建實(shí)例。
8.parent?
如果兩個(gè)Bean?的屬性裝配信息很相似,那么可以利用繼
承來減少重復(fù)的配置工作。
<!--?裝配Bean?的繼承
父類作為模板,不需要實(shí)例化,設(shè)置abstract=”true”-->
`?<bean?id=”parent”?class=”cn.csdn.service.Parent”
abstract=”true”>
<property?name=”name”?value=”z_xiaofei168”/>
<property?name=”pass”?value=”z_xiaofei168”/>
</bean>
<!--?裝配Bean?的繼承
子類中用parent?屬性指定父類標(biāo)識(shí)或別名
子類可以覆蓋父類的屬性裝配,也可以新增自己的屬性裝配
-->
`?<bean?id=”child”?class=”cn.csdn.service.Chlid”
parent=”parent”>
<property?name=”pass”?value=”123123”/>
<property?name=”age”?value=”22”/>
</bean>
三:裝配Bean?的各種類型屬性值
1..簡(jiǎn)單類型屬性值的裝配
[html]?view plaincopy print?
2.引用其他Bean?的裝配
[html]?view plaincopy print?
另外一種不常使用的配置方式是在property?元素中嵌入
一個(gè)bean?元素來指定所引用的Bean.
[html]?view plaincopy print?
3.集合的裝配
其實(shí)集合的裝配并不是復(fù)雜,反而感覺到很簡(jiǎn)單,用一個(gè)例子來說明問題吧:
配置如下:
[html]?view plaincopy print?
四:Spring?bean生命周期
? ??? 在傳統(tǒng)的Java應(yīng)用中,Bean的生命周期非常簡(jiǎn)單。?Java的關(guān)鍵詞new用來實(shí)例化Bean(或許他是非序列化的)。這樣就夠用了。?相反,Bean的生命周期在Spring容器中更加細(xì)致。?理解Spring?Bean的生命周期非常重要,因?yàn)槟慊蛟S要利用Spring提供的機(jī)會(huì)來訂制Bean的創(chuàng)建過程。?
?bean生命周期
1.容器尋找Bean的定義信息并且將其實(shí)例化。?
2.受用依賴注入,Spring按照Bean定義信息配置Bean的所有屬性。?
3.如果Bean實(shí)現(xiàn)了BeanNameAware接口,工廠調(diào)用Bean的setBeanName()方法傳遞Bean的ID。?
4.如果Bean實(shí)現(xiàn)了BeanFactoryAware接口,工廠調(diào)用setBeanFactory()方法傳入工廠自身。?
5.如果BeanPostProcessor和Bean關(guān)聯(lián),那么它們的postProcessBeforeInitialzation()方法將被調(diào)用。?
6.如果Bean指定了init-method方法,它將被調(diào)用。?
7.最后,如果有BeanPsotProcessor和Bean關(guān)聯(lián),那么它們的postProcessAfterInitialization()方法將被調(diào)用。?
到這個(gè)時(shí)候,Bean已經(jīng)可以被應(yīng)用系統(tǒng)使用了,并且將被保留在Bean?Factory中知道它不再需要。?
有兩種方法可以把它從Bean?Factory中刪除掉。?
1.如果Bean實(shí)現(xiàn)了DisposableBean接口,destory()方法被調(diào)用。?
2.如果指定了訂制的銷毀方法,就調(diào)用這個(gè)方法。?
Bean在Spring應(yīng)用上下文的生命周期與在Bean工廠中的生命周期只有一點(diǎn)不同,?唯一不同的是,如果Bean實(shí)現(xiàn)了ApplicationContextAwre接口,setApplicationContext()方法被調(diào)用。?
只有singleton行為的bean接受容器管理生命周期。?
non-singleton行為的bean,Spring容器僅僅是new的替代,容器只負(fù)責(zé)創(chuàng)建。?
對(duì)于singleton?bean,Spring容器知道bean何時(shí)實(shí)例化結(jié)束,何時(shí)銷毀,?Spring可以管理實(shí)例化結(jié)束之后,和銷毀之前的行為,管理bean的生命周期行為主要未如下兩個(gè)時(shí)機(jī):?
Bean全部依賴注入之后?
Bean即將銷毀之前?
1)依賴關(guān)系注入后的行為實(shí)現(xiàn):?
有兩種方法:A.編寫init方法??B.實(shí)現(xiàn)InitializingBean接口?
afterPropertiesSet和init同時(shí)出現(xiàn),前者先于后者執(zhí)行,使用init方法,需要對(duì)配置文件加入init-method屬性?
2)bean銷毀之前的行為?
有兩種方法:A.編寫close方法??B.實(shí)現(xiàn)DisposableBean接口?
destroy和close同時(shí)出現(xiàn),前者先于后者執(zhí)行,使用close方法,需要對(duì)配置文件加入destroy-method屬性?
?總體上分只為四個(gè)階段??
?1.?BeanFactoyPostProcessor實(shí)例化??
?2.?Bean實(shí)例化,然后通過某些BeanFactoyPostProcessor來進(jìn)行依賴注入??
?3.?BeanPostProcessor的調(diào)用.Spring內(nèi)置的BeanPostProcessor負(fù)責(zé)調(diào)用Bean實(shí)現(xiàn)的接口:?BeanNameAware,?BeanFactoryAware,?ApplicationContextAware等等,等這些內(nèi)置的BeanPostProcessor調(diào)用完后才會(huì)調(diào)用自己配置的BeanPostProcessor??
?4.Bean銷毀階段??
注:xml依賴注入中的bean.xml例子:
[html]?view plaincopy print?
總結(jié)
以上是生活随笔為你收集整理的Java程序员从笨鸟到菜鸟之(七十)细谈Spring(三)IOC和spring基本配置详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java程序员从笨鸟到菜鸟之(十三)ja
- 下一篇: Java程序员从笨鸟到菜鸟之(七十三)细