IOC&DI概述
1.IOC(Inversion of Control):其思想是反轉資源獲取的方向.傳統的資源查找方式要求組件向容器發起請求查找資源.作爲迴應,容器適時的返回資源.而應用了IOC之後,則是容器主動地將資源推送給它所管理的組件,組件所要做的僅是選擇一種合適的方式來接受資源.這種行爲也被稱爲查找的被動形式
2.DI(Dependency Injection)——IOC的另一種表述方式:即組件以一些預先定義好的方式(例如setter方法)接受來自如容器的資源注入.相對於IOC而言,這種表述更直接
配置bean
- 配置形式:基於XML文件的方式;基於註解的方式
- ApplicationContext主要實現類:
- ClassPathXmlApplicationContext:從類路徑下加載配置文件
- FileSystemXmlApplicationContext:從文件系統中加載配置文件
- ConfigurableApplicationContext擴展於ApplicationContext,新增加兩個主要方法:refresh()和close(),讓ApplicatContext具有啓動、刷新、和關閉上下文的能力
- ApplicationContext在初始化上下文時就實例化所有單例的Bean
- WebApplicationContext是專門爲WEB應用而準備的,它允許從相對於WEB根目錄的路徑中完成初始化工作
- ApplicationContext主要實現類:
自動裝配
- Spring IOC容器可以自動裝配Bean.需要做的僅僅是在
<bean>
的autowire屬性裏指定自動裝配的模式
- byType(根據類型自動裝配):若IOC容器中有多個與目標Bean類型一致的Bean.在這種情況下,Spring將無法判定拿個Bean最合適該屬性,所以不能執行自動裝配(需要唯一)
- byName(根據名稱自動裝配):必須將目標Bean的名稱和屬性名設置的完全相同(需要唯一)
- constructor(通過構造器自動裝配):當Bean中存在多個構造器時,此種自動裝配方式將會很複雜(不推薦使用)
- 自動裝配不夠靈活
Bean之間的關係(繼承、依賴)
- 繼承:使用
<bean>
標籤的parent屬性
- Spring允許繼承bean的配置,被繼承的bean稱爲父bean.繼承這個父Bean的Bean稱爲子Bean
- 子Bean從父Bean中繼承配置,包括Bean的屬性配置
- 子Bean也可以覆蓋從父Bean繼承過來的配置
- 父Bean可以作爲配置模板,也可以作爲Bean實例.若只想把父Bean作爲模板,可以設置
<bean>
的abstract屬性爲true,這樣Spring將不會實例化這個Bean - 並不是
<bean>
元素裏的所有屬性都會被繼承.比如:autowire,abstract等 - 也可以忽略父Bean的class屬性,讓子Bean指定自己的類,而共享相同的屬性配置.但此時abstract必須設爲true
- 依賴:Spring允許用戶通過depends-on屬性設定Bean前置依賴的Bean,前置依賴的Bean會在本Bean實例化之前創建好
- 如果前置依賴於多個Bean,則可以通過逗號,空格或的方式配置Bean的名稱
Bean的作用域:singleton;prototype;WEB環境作用域
- 用bean標籤的scope屬性設置作用域
- 默認是單例模式/singleton。(每次調用都是同一個實例,在加在配置文件時就會創建實例)
- prototype:原型。每次都會獲取一個新的實例,在請求實例時纔會創建實例
使用外部屬性文件
- 在配置文件裏配置Bean時,有時需要在Bean的配置裏混入系統部署的細節信息(例如:文件路徑,數據源配置信息等)。而這些部署細節實際上需要和Bean配置相分離
- Spring提供了一個PropertyPlaceholderConfigurer的BeanFactory後置處理器(即
<context:property-placeholder>
標籤),這個處理器允許用戶將Bean配置的部分內容外移到屬性文件中。可以在Bean配置文件裏使用形式爲${var}的變量,並使用這些屬性來替代變量 - Spring還允許在屬性文件中使用${propName},以實現屬性之間的相互引用
SpEL(Spring表達式語言)
- Spring表達式語言(簡稱SpEL):是一個支持運行時查詢和操作對象圖的強大的表達式語言
- 語法類似EL:SpEL使用#{…}作爲定界符,所有在大括號中的字符都將被認爲是SpEL
- SpEL爲bean的屬性進行動態賦值提供了便利
- 通過SpEL可以實現:
- 通過bean的id對bean進行引用
- 調用方法以及引用對象中的屬性
- 計算表達式的值
- 正則表達式的匹配
- 字面量的表示:
- 整數:
<property name="count" value="#{5}" / >
- 小數:
<property name="frequency" value="#{89.7}" / >
- 科學計數法:
<property name="capacity" value="#{1e4}" / >
- String可以使用單引號或者雙引號作爲字符串的定界符號:
<property name="name" value="#{"Chuck"}" / >
或<property name='name' value='#{"Chuck"}' / >
- Boolean:
<property name="enabled" value="#{false}" / >
- 整數:
- 引用Bean、屬性和方法:
- 引用其他對象
- 引用其他對象的屬性
- 調用其他方法,還可以鏈式操作
- 調用靜態方法或靜態屬性:通過T(className)調用一個類的靜態方法,它將返回一個Class Object,然後再調用相應的方法或屬性
- SpEL支持的運算符號
- 算術運算符:+、-、*、/、%、^
- 加號還可以用作字符串連接
- 比較運算符:<、>、==、<=、>=、lt、gt、eq、le、ge
- 邏輯運算符:and、or、not、|
- if-else運算符:?:(temary),?:(Elvis)
- if-else的變體
- 正則表達式:matches
Spring管理Bean的生命週期
- Spring IOC容器可以管理Bean的生命週期,Spring允許在Bean生命週期的特定點執行定製的任務
- Spring IOC容器對Bean的生命週期進行管理的過程:
- 通過構造器或工廠方法創建Bean實例
- 爲Bean的屬性設置值和對其他Bean的引用
- 調用Bean的初始化方法
- Bean可以使用了
- 當容器關閉時,調用Bean的銷燬方法
- 在Bean的聲明裏設置init-method和destory-method屬性,爲Bean指定初始化和銷燬方法
- 創建Bean後置處理器
- Bean後置處理器允許在調用初始化方法前後對Bean進行額外的處理
- Bean後置處理器對IOC容器裏的所有Bean實例逐一處理,而非單一實例。其典型應用是:檢查Bean屬性的正確性或根據特定的標準更改Bean的屬性
- 對Bean後置處理器而言,需要實現Interface BeanPostProcessor接口。在初始化方法被調用前後,Spring將把每個Bean實例分別傳遞給上述接口的以下兩個方法:postprocessafterinitialization(Object bean, String beanName)和postprocessbeforeinitialization(Object bean, String beanName)
- 可以在以上兩個方法中修改返回的Bean,甚至返回一個新的Bean
- 配置Bean的後置處理器不需要配置id,IOC容器會自動識別BeanPostProcessor
- Spring IOC容器對Bean的生命週期進行管理的過程:
- 通過構造器或工廠方法創建Bean實例
- 爲Bean的屬性設置值和對其他Bean的引用
- 將Bean實例傳遞給Bean後置處理器的和postprocessbeforeinitialization方法
- 調用Bean實例傳遞給Bean後置處理器的postprocessafterinitialization方法
- Bean可以使用了
- 當容器關閉時,調用了Bean的銷燬方法
通過工廠方法配置Bean
- 靜態工廠方法:
- 在bean的class屬性裏指定擁有該工廠方法的Bean
- 在factory-method屬性裏指定該工廠方法的名稱
- 使用construtor-arg元素爲工廠方法傳遞方法參數
- 實例工廠方法:將對象的創建過程封裝到另外一個對象實例的方法裏。當客戶端需要請求對象時,只需要簡單的調用該實例方法而不需要關心對象的創建細節
- 要聲明通過實例工廠方法創建的Bean
- 在bean的factory-bean屬性裏指定擁有該工廠方法的Bean
- 在factory-method屬性裏指定該工廠方法的名稱
- 使用construtor-arg元素爲工廠方法傳遞方法參數
通過FactoryBean配置Bean
- 自定義的FactoryBean需要實現FactoryBean接口
- 配置文件中通過FactoryBean來配置Bean的實例,class指向FactoryBean的屬性,但實際返回的實例卻是FactoryBean的getObject()方法返回的實例
通過註解配置Bean
- 組件掃描(component scanning):Spring能夠從classpath下自動掃描,偵測和實例化具有特定註解的組件
- 當在組件類上使用了特定的註解之後,還需要在Spring的配置文件中聲明
<context:component-scan>
- base-package屬性指定一個需要掃描的基類包,Spring容器將會掃描這個基類包裏及其子包中的所有類
- 當需要掃描多個包時,可以使用逗號分隔
- 如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性指定特定的類,實例:
<context:component-scan base-package="com.beans" resource-pattern="autowire/*.class">
<context:include-filter>
子節點表示要包含的目標類,使用這個節點時需要將use-default-filters屬性設置爲false<context:exclude-filter>
子節點表示要排除在外的目標類<context:component-scan>
下可以擁有若干個<context:include-filter>
和<context:exclude-filter>
子節點
<context:include-filter>
和<context:exclude-filter>
子節點支持多種類型的過濾表達式:
- 當在組件類上使用了特定的註解之後,還需要在Spring的配置文件中聲明
類別 | 示例 | 說明 |
---|---|---|
annotation | com.XxxAnnotation | 所有標註了XxxAnnotation的類,該類型採用目標類是否標註了某個註解進行過濾 |
assignable | com.XxxService | 所有繼承或擴展XxxService的類,該類型採用目標類是否繼承或擴展某個特定類進行過濾 |
aspectj | com.*Service+ | 所有類名以Service結束的類及繼承或擴展它們的類。該類型採用AspejctJ表達式進行過濾 |
regex | com.\anno.* | 所有com.anno包下的類,該類型採用正則表達式根據類的類名進行過濾 |
custom | com.XxxTypeFilter | 採用XxxTypeFilter通過代碼的方式定義過濾規則。該類必須實現org.springframework.core.type.TypeFilter接口 |
2. 特定組件包括:
1. @Component:基本註解,標識了一個受Spring管理的組件
2. @Respository:標識持久層組件
3. @Service:標識服務層(業務層)組件
4. @Controller:標識表現層組件
3. 對於掃描到的組件,Spring有默認的命名策略:使用非限定類名,第一個字母小寫.也可以在註解中通過value屬性值標識組件的名稱
4. 組件裝配:<context:component-scan>
元素還會自動註冊AutowiredAnnotationBeanPostProcessor實例,該實例可以自動裝配具有@Autowired和@Resource、@Inject註解的屬性
1. @Autowired註解自動裝配具有兼容類型的單個Bean屬性
1. 構造器、普通字段(即使是非public),一切具有參數的方法都可以應用@Autowired註解
2. 默認情況下,所有使用@Autowired註解的屬性都需要被設置,當Spring找不到匹配的Bean裝配屬性時,會拋出異常,若一屬性允許不被設置,可以設置@Autowired註解的required屬性爲false
3. 默認情況下,當IOC容器裏存在多個類型兼容的Bean時,通過類型的自動裝配將無法工作.此時可以在@Qualifler註解裏提供Bean的名稱.Spring允許對方法的入參標註@Qualifiter已指定注入Bean的名稱
4. @Autowired註解也可以應用在數組類型的屬性上,此時Spring將會把所有匹配的Bean進行自動裝配
5. @Autowired註解也可以應用在集合屬性上,此時Spring讀取該集合的類型信息,然後自動裝配所有與之兼容的Bean.
6. @Autowired註解在java.util.Map上時,若該Map的鍵值爲String,那麼Spring將自動裝配與之Map值類型兼容的Bean,此時Bean的名稱作爲鍵值
2. 使用@Resource或@Inject自動裝配Bean
1. Spring還支持@Resource和@Inject註解,這兩個註解和@Autowired註解的功能類似
2. @Resource註解要求提供一個Bean名稱的屬性,若該屬性爲空,則自動採用標註處的變量或方法名作爲Bean的名稱
3. @Inject和@Autowired註解一樣也是按類型匹配注入的Bean,但沒有reqired屬性
4. 建議使用@Autowired註解
泛型依賴注入
Spring 4.x中可以爲子類注入子類對應的泛型類型的成員變量的引用