關於spring中bean配置的幾件小事

一.IOC和DI

1.IOC(Inversion of Control)

其思想是反轉資源獲取的方向。傳統的資源查找方式要求組件向容器發起請求查找資源,做爲迴應,容器適時的返回資源;而應用了IOC以後,則是容器主動的將資源推送給它所管理的組件,組件所要作的僅是選擇一種合適的方式來接收資源。這種行爲也被成爲查找的被動形式。java

2.DI(Dependency Injection)

IOC的另外一種表達方式:即組件的一些預先定義好的方式(例如:setter方法)接受來自如容器的資源注入。相對於IOC而言,這種表述更直接。web

3.IOC的前世此生

使用這樣一個需求,生成HTML或者PDF格式的不一樣類型的報表爲例,說明IOC的演變。
①分離接口設計正則表達式

②採用工廠模式spring

③採用反轉控制數組

二.spring配置bean

1.在spring的IOC容器裏面配置Bean。

在xml文件中經過bean節點來配置beanspring-mvc

<bean id="helloWorld" 
         class="com.desperado.helloworld.HelloWorld >
</bean>

id:Bean的名稱。服務器

  • 在IOC容器中必須是惟一的.
  • 若id沒有指定,Spring會自動將全限定性類名做爲Bean名稱。
  • id能夠指定多個名字,名字之間能夠用逗號、分號、或空格隔開。

2.Spring容器

  • 在Spring IOC容器讀取Bean配置建立Bean實例以前,必須對它進行實例化。只有在容器實例化以後,才能夠從IOC容器裏面獲取Bean實例並使用。
  • Spring提供了兩種類型的IOC容器實現
    • BeanFactory:IOC容器的基本實現。
    • ApplicationContext:提供了更多的高級特性,是BeanFactory的子接口。
    • BeanFactory是Spring框架的基礎設施,面向Spring自己。ApplicationContext面向使用Spring框架的開發者,幾乎全部的應用場合都直接使用ApplicationContext而非底層的BeanFactory。
    • 不管使用何種方式,配置文件是相同的。

3.ApplicationContext

  • ApplicationContext的主要實現類:
    • ClassPathXmlApplicationContext:從類路徑下面加載配置文件。
    • FileSystemXmlApplicationContext:從文件系統中加載配置文件。
  • ConfigurableApplicationContext擴展於ApplicationContext,新增長兩個主要方法:refresh()和close(),讓ApplicationContext具備啓動、刷新和關閉上下文的能力。
  • ApplicationContext在初始化上下文時就實例化全部單例的Bean。
  • WebApplicationContext是專門爲WEB應用而準備的,它容許從相對於WEB根目錄的路徑中完成初始化工做.。

  • 調用ApplicationContext的getBean()方法能夠獲取到Bean。

4.依賴注入的三種方式

  • 屬性注入
    屬性注入即經過setter方法注入Bean的屬性值或依賴的對象。
    屬性注入使用 元素,使用name屬性指定Bean的屬性名稱,value屬性或 子節點指定屬性值。
    屬性注入是實際應用中最經常使用的注入方式。
<bean id="helloWorld"   class="com.desperado.helloworld.HelloWorld">
      <property name="userName" value="desperado"></property>
</bean>
  • 構造器注入
    經過構造方法注入Bean的屬性值或依賴的對象,它保證了Bean實例在實例化後就可使用。
    構造器注入在 元素裏聲明屬性, 中沒有name屬性。
    • 按索引匹配入參
    <bean id="car" class ="com.desperado.helloworld.Car">
        <constructor-arg value="奧迪" index="0"></constructor-arg>  
        <constructor-arg value="奔馳" index="1"></constructor-arg>  
        <constructor-arg value="5000" index="2"></constructor-arg>  
    </bean>
    • 按匹配參數注入
    <bean id="car" class ="com.desperado.helloworld.Car">
        <constructor-arg value="奧迪" type="java.lang.String"></constructor-arg>  
        <constructor-arg value="奔馳" type="java.lang.String"></constructor-arg>  
        <constructor-arg value="5000" type="java.lang.double"></constructor-arg>  
    </bean>
  • 工廠方法注入(不多使用,不推薦)session

  • 注入屬性值細節
    • 字面值:可用字符串表示的值,能夠經過 元素標籤或value屬性進行注入。
    • 基本數據類型及其封裝類、String等類型均可以採起字面值的注入。
    • 若字面值中包含特殊字符,可使用<[CDATA[]]把字面值包裹起來。

5. 引用其餘Bean

  • 組成應用程序的Bean常常須要相互協做以完成應用程序的功能,要使Bean可以相互訪問,就必須在Bean配置文件中指定對Bean的引用。
  • 在Bean的配置文件中,能夠經過 元素或ref屬性爲Bean的屬性或構造器參數指定對Bean的引用。
  • 也能夠在屬性或構造器裏包含Bean的聲明,這樣的Bean成爲內部Bean。
<bean id="service" class="com.desperado.helloworld.Service"></bean> 

<bean id="action" class="com.desperado.helloworld.Action">
      <property name="service" ref="service"></property>
</bean>

6.內部bean

  • 當Bean實例僅僅給一個特定的屬性使用時,能夠將其聲明爲內部Bean,內部Bean聲明直接包含在 或者 元素裏,不須要設置任何id或name屬性。
  • 內部Bean不能使用在任何其餘部分。mvc

    7.null值和級聯屬性

  • 可使用專用的 元素標籤爲Bean的字符串或其它對象類型的屬性注入null值。
  • Spring支持級聯屬性的配置。app

8.集合屬性

  • 在Spring中能夠經過一組內置的xml標籤(例如 , , )來配置集合屬性。
  • 配置java.util.List類型的屬性,須要指定 標籤,在標籤裏包含一些元素。這些標籤能夠經過 指定簡單的常量值。這些標籤能夠經過 指定簡單的常量值,經過 指定對其餘Bean的引用。經過 指定內置Bean的定義,經過 指定空元素,甚至能夠內嵌其餘集合。
  • 數組的定義和List同樣,都使用
  • 配置java.util.Set須要使用 標籤,定義元素的方法與List同樣。
  • java.lang.Map經過標籤訂義,標籤裏可使用多個 做爲子標籤,每一個條目包含一個鍵和一個值。
  • 必須在 標籤裏定義鍵。
  • 由於鍵和值的類型沒有限制,索引能夠自由的爲它們指定 , , 元素。
  • 能夠將Map的鍵和值做爲 的屬性定義:簡單常量使用key和value定義;Bean引用經過key-ref和value-ref屬性定義。
  • 使用 定義java.util.Properties,該標籤使用多個 做爲子標籤,每一個 標籤必須定義key屬性。

9.使用utility scheme定義集合

  • 使用基本的集合標籤訂義集合時,不能將集合做爲獨立的Bean定義,致使其餘Bean沒法引用該集合,因此沒法再不一樣Bean之間共享集合。
  • 可使用util schema裏的集合標籤訂義獨立的集合Bean。須要注意的是,必須在 根元素裏添加util schema定義。

10.使用P命名空間

  • 爲了將XML文件的配置愈來愈多的XML文件採用屬性而非子元素配置信息。
  • Spring從2.5開始引入了一個新的p命名空間,能夠經過 元素屬性的方式配置Bean的屬性。
    -使用p命名空間後,基於XML的配置方式將進一步簡化。

三.XML配置裏的Bean自動裝配

  • Spring IOC容器能夠自動裝配Bean,須要作的僅僅是在 的autowire屬性裏指定自動裝配的模式。
  • byType(根據類型自動裝配):若IOC容器中有多個與目標Bean類型一致的Bean。在這種狀況下,Spring將沒法斷定哪一個Bean最適合該屬性,索引不能執行自動裝配。
  • byName(根據名稱自動裝配):必須將目標Bean的名稱和屬性名設置的徹底相同。
  • constructor(經過構造器自動裝配):當Bean中存在多個構造器時,此種自動裝配方式將會很複雜,不推薦使用。

缺點

  • 在Bean配置文件裏設置autowire屬性進行自動裝配將會裝配Bean的全部屬性,而後,若只但願裝配個別屬性時,autowire屬性就不夠靈活了。
  • autowire屬性要麼根據類型自動裝配,那麼根據名稱自動裝配,不能二者兼而有之。
  • 通常狀況下,在實際的項目之中不多使用自動裝配功能,由於和自動裝配功能所帶來的好處比起來,明確清晰的配置文檔更好。

四.Bean之間的關係:繼承和依賴

1.繼承Bean配置

  • Spring容許繼承Bean的配置,被繼承的Bean稱爲父bean,繼承這個父bean的bean稱爲子bean。
  • 子Bean從父Bean中繼承配置,包括Bean的屬性配置。
  • 子Bean也能夠覆蓋從父Bean繼承過來的配置。
  • 父Bean能夠做爲配置模板,也能夠做爲bean實例。若只想把父bean做爲模板,能夠設置 的abstract屬性爲true,這樣Spring將不會實例化這個Bean。
  • 並非 元素裏的全部屬性都會被繼承。好比autowire、abstract等。
  • 也能夠忽略父Bean的class屬性,讓子Bean指定本身的類,而共享相同的屬性配置,但此時abstract必須設爲true。

    2.依賴Bean配置

  • Spring容許用戶經過depends-on屬性設定Bean前置依賴的Bean,前置依賴的Bean會在本Bean實例化以前建立好。
  • 若是前置依賴於多個Bean,則能夠經過逗號、空格的方式配置Bean的名稱。

    五.bean的做用域

  • 在Spring中,能夠在 元素的scope屬性裏設置Bean的做用域。
  • 默認狀況下,Spring只爲每一個在IOC容器裏面聲明的Bean建立惟一一個實例,整個IOC容器範圍內都能共享該實例:全部後續的getBean()調用和Bean引用都將返回這個惟一的Bean實例。該做用域被稱爲singleton,它是全部bean的默認做用域。

類別 說明
singleton 在SpringIOC容器中僅存在一個Bean實例,Bean以單實例的方式存在
prototype 每次調用getBean()時都會返回一個新的實例
request 每次HTTP請求都會建立一個新的Bean,該做用域僅適用於WebApplicationContext環境
session 同一個HTTP session共享一個Bean,不一樣的HTTP Session使用不一樣的Bean。該做用域僅適用於WebApplicationContext環境。
globalSession 通常用於protlet應用環境,該做用域僅適用於WebApplicationContext環境。

六.使用外部屬性文件

1.在配置文件裏配置Bean時,有時須要在Bean的配置裏混入系統部署的細節信息(例如:文件路徑,數據源配置信息等)。而這些部署細節實際上須要和Bean配置相分離。

2.Spring提供了一個PropertyPlaceholderConfigurer的BeanFactory後置處理器,這個處理器容許用戶將Bean配置的部份內容外移到屬性文件中。能夠在Bean配置文件裏使用形式爲 ${var} 的變量,PropertyPlaceholderConfigurer從屬性文件里加載屬性,並使用這些屬性來替換變量。

3.Spring還容許在屬性文件中使用${propName},以實現屬性直接的相互做用。

4.註冊PropertyPlaceholderConfigurer
Spring2.0的配置方式:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="location" value="classpath:jdbc.properties"></property>
</bean>

Spring2.5以後:可經過 元素簡化:

  • 中添加context Schema定義
  • 在配置文件中加入以下配置
<context:property-placeholder location="classpath:db.properties" />

七.SpEL

1.Spring表達式語言(簡稱SpELl):是一個支持運行時查詢和操做對象圖的強大的表達式語言。

  • 語法相似於EL:SpELl使用#{...}做爲界定符,全部再打括號中的字符都被認爲是SpEL
  • SpEL爲bean的屬性進行動態賦值提供了便利。
  • 經過SpELl能夠實現:
    • 經過bean的id對bean進行引用。
    • 經過方法以及引用對象的中的屬性
    • 計算表達式的值
    • 正則表達式的匹配

2.SpELl的字面量

  • 字面量的表示
    • 整數:
    • 小數:
    • 科學計數法:
    • String可使用單引號或者雙引號做爲字符串的界定符號: .
    • booean:

3.引用Bean、屬性和方法

  • 應用其餘對象
    經過value屬性和SpELl配置bean之間的關係
<property name="prefix" value="#{prefixGenerator}"/>
  • 引用其餘對象的屬性
    經過value屬性和SpELl配置suffix屬性值爲另外一個Bean的suffix屬性值
<property name="suffix" value="#{sequenceGenerator2.suffix}"/>
  • 調用其餘方法,還能夠鏈式操做
    經過value屬性和SpELl配置suffix屬性值爲另外一個Bean的方法的返回值
<property name="suffix" value="#{sequenceGenerator2.toString()}"/>

方法的鏈式操做

<property name="count" value="#{sequenceGenerator2.toString().toUpperCase()}"/>

-調用靜態方法或靜態屬性:經過T()調用一個類的靜態方法,它將返回一個Class Object,而後再調用相應的方法或屬性。

<property name="initValue" value="#{T(java.lang.Math).PI}"></property>

4. SpEL支持的運算符號

  • 數學運算符:+,-,*,/,%,^:
  • 加好還能夠用做字符串的鏈接。
  • 比較運算符:<,>,==,<=,>=,lt,gt,eq,le,ge
  • 邏輯運算符:and,or,not,|
  • if-else運算符:?:(ternary),?:(Elvis)
  • if-else的變體
  • 正則表達式:matches

八.Bean的生命週期

1.IOC容器中Bean的生命週期方法

  • Spring IOC容器能夠管理Bean的生命週期,Spring容許在Bean生命週期的特定點執行定製的任務。
  • SpringIOC容器對Bean的生命週期進行管理的過程:
    1. 經過構造器或工廠方法建立Bean實例。
    2. 爲Bean的屬性設置值和對其餘Bean的引用。
    3. 調用Bean的初始化方法。
    4. Bean可使用了。
    5. 當容器關閉了,調用Bean的銷燬方法。
  • 在Bean的聲明裏設置init-method和destroy-method屬性,爲Bean指定初始化和銷燬方法。

    2.建立Bean後置處理器

  • Bean後置處理器容許在調用初始化方法先後對Bean進行額外的處理。
  • Bean後置處理器對IOC容器裏的全部Bean實例逐一處理,而非單一實例。其典型應用是:檢查Bean屬性的正確性或根據特定的標準更改Bean的屬性。
  • 對Bean後置處理器而言,須要實現BeanPostProcessor接口。在初始化方法被調用先後,Spring將把每一個Bean實例分別傳遞給上述接口的postProcessAfterInitialization()方法和postProcessBeforeInitialization()方法。

    3.添加後置處理器後Bean的生命週期

    SpringIOC容器對Bean的生命週期進行管理的過程:
    1. 經過構造器或工廠方法建立Bean實例。
    2. 爲Bean的屬性設置值和對其餘Bean的引用。
    3. 將Bean實例傳遞給Bean後置處理器的postProcessBeforeInitialization()方法。
    4. 調用Bean的初始化方法。
    5. 將Bean的實例傳遞給Bean的後置處理器的postProcessAfterInitialization()方法。
    6. Bean能夠正常使用了。
    7. 當容器關閉時,調用Bean的銷燬方法。

      4.經過調用靜態工廠方法建立Bean

  • 調用靜態工廠方法建立Bean是將對象建立的過程封裝到靜態方法中。當客戶端須要對象時,只須要簡單地調用靜態方法,而不用關心建立對象的細節。
  • 要聲明經過靜態方法建立的Bean,須要在Bean的class屬性裏面這麼擁有該工廠的方法的類,同時在factory-method屬性裏指定工廠方法的名稱。最後使用 元素爲該方法傳遞方法參數。

    5.經過調用實例工廠方法建立Bean

  • 實例工廠方法:將對象的建立過程封裝到另一個對象實例的方法裏。當客戶端須要請求對象時,只須要簡單的調用該實例方法而不須要關係對象的建立細節。
  • 要聲明經過實例工廠方法建立的Bean
    • 在bean的factory-bane屬性裏指定擁有該工廠方法的bean。
    • 在factory-method屬性裏指定該工廠方法的名稱。
    • 使用constructor-arg元素爲工廠方法傳遞方法參數。

      6.實現FactoryBean接口在SpringIOC容器中配置Bean

  • Spring中有兩種類型的Bean,一種是普通Bean,另外一種是工廠Bean,即FactoryBean。
  • 工廠Bean跟普通Bean不一樣,其返回的對象不是指定類的一個實例,其返回的是該工廠Bean的getObject方法所返回的對象。

    九.組件裝配

    1.在classpath中掃描組件

  • 組件掃描:spring可以從classpath下自動掃描,偵測和實例化具備特定註解的組件。
  • 特定組件包括:
    1. @Component:基本註解,標識了一個受Spring管理的組件。
    2. @Responsitory:標識持久層組件。
    3. @Service:標識服務層(業務層)組件。
    4. @Controller:標識表現出組件。
  • 對於掃描到的組件,Spring有默認的命名策略:使用非限定類名,第一個字母小寫。也能夠在註解中經過value屬性值標識組件的名稱。
  • 當在組件類上使用了特定的註解以後,還須要在Spring的配置文件聲明
    • base-package屬性制定一個要掃描的基類包,Spring容器將會掃描這個基類包及其子包中的全部類。
    • 當須要掃描多個包時,可使用逗號隔開。
    • 若是僅但願掃描特定的類而非基類包下的全部類,可以使用resource-pattern屬性過濾特定的類。

    • 子節點表示要包含的目標類。
    • 子節點表示要排除在外的目標類。
    • 下面能夠擁有若干個 子節點。
    <context:component-scan base-package="com.desperado.helloworld" resource-pattern="autowire/*.class />
  • 子節點支持多種類型的過濾表達式。

類別 示例 說明
annotation com.desperado.XxxAnnotation 全部標註了XXXAnnotation的類。該類型採用目標;類是否標註了某個註解進行過濾。
assinable com.desperado.XxxService s全部繼承或擴展XXXService的類。該類型採用目標類是否繼承或擴展某個特定類進行過濾。
aspectj com.desperado..*Service+ 全部類名以Service結尾的類以及繼承或擴展它們的類。該類型採用AspectJ表達式進行過濾
regex com.desperado.anno..* 全部com.desperado.anno包下面的類。該類型採用正則表達式根據類的類名進行過濾。
custom com.desperado.XxxTypeFilter 採用XXXTypeFilter經過代碼的方式定義過濾規則。該類必須實現org.springframework.core.type.TypeFilter接口
  • 元素還會自動註冊AutowiredAnnotationBeanPostProcessor實例,該實例能夠自動裝配具備@Autowired和@Resource、@Inject註解的屬性。

    2.使用@Autowired自動裝配Bean

    @Autowired註解自動裝配具備兼容類型單個Bean屬性。
    • 構造器,普通字段(即便是非public),一切具備參數的方法均可以應用@Autowired註解。
    • 默認狀況下,全部使用@Autowired註解的屬性都須要被設置。當Spring找不到匹配的Bean裝配屬性時,會拋出異常,若某一屬性容許不被設置,能夠設置@Autowired註解的required屬性爲false。
    • 默認狀況下,當IOC容器裏存在多個類型兼容的Bean時,經過類型的自動裝配將沒法工做,此時能夠在@Qualifier註解裏提供Bean的名稱。Spring容許對方法的入參標準@Qualifiter已指定Bean的名稱。
    • @Autowired註解也能夠應用在數組類型的屬性上,此時Spring將會把全部匹配的Bean進行自動裝配。
    • @Autowired註解也能夠應用在集合屬性上,此時Spring讀取該集合的類型信息,而後自動裝配全部與之兼容的Bean。
    • @Autowired註解用在java.util.Map上時,若該Map的鍵值爲String,那麼Spring將自動裝配與之Map值類型兼容的Bean,此時Bean的名稱做爲鍵值。

3.使用@Resource或@Inject自動裝配Bean

  • Spring還指出@Resource和@Inject註解,這兩個註解和@Autowired註解的功用相似。
  • @Resource註解要求提供一個Bean名稱的屬性,若該屬性爲空,則自動採用標註處的變量或方法名做爲Bean的名稱。
  • @Inject和@Autowired註解同樣也是按類型匹配注入的Bean,但沒有required屬性。
  • 建議使用@Autowired註解

    十.泛型依賴注入

    Spring4.x中能夠爲子類注入子類對應的泛型類型的經常使用變量的引用。

十一.整個多個配置文件

Spring容許經過 將多個配置文件引入到一個文件中,進行配置文件的集成。這樣在啓動Spring容器時,僅須要指定這個合併好的配置文件就能夠。
import元素的resource屬性支持Spring的標準的路徑資源

地址前綴 示例 對應資源類型
classpath: classpath:spring-mvc.xml 從類路徑下加載資源,classpath:和classpath:/是等價的
file: file:/conf/security/spirng-shiro.xml 從文件系統目錄中裝載資源,可採用絕對或相對路徑
http:// http:///www.desperado.com/resource/beans.xml 從web服務器中加載資源
ftp:// ftp://www.desperado.com/resource/beans.xml 從FTP服務器中加載資源。
相關文章
相關標籤/搜索