Spring入門之初識IoC和AOP
Bean
配置
配置好的bean可以直接通過spring的上下文獲取。
而配置只用告訴spring,一個xml檔案的路徑,spring就會基於這個xml生成一個對應的context
物件。
類似 Bean b = context.getBean("Bean.id")
.
配置項
-
id 唯一標識
-
class 具體要例項化的類
-
scope 範圍/作用域
- singleton 一個Bean容器只存在一份,但是可以基於一份xml檔案生成兩個context,這兩個context容器可以有各自的單例物件
- prototype 每次請求/使用時建立新的例項,destroy不生效,自動回收
- request 每次http請求
- session
- global session 基於portlet(連線多個系統,例如OA、HR系統)的web應用中有效
-
constructor arg 構造器引數
-
properties 屬性
-
Autowiring mode 自動裝配的方式
-
lazy-initialization mode
-
initialization/destruction method
XML方式
spring-ioc.xml
<beans>
<bean id="oneInterface"
class="com.tuo.interface.OneInterfaceImpl" ></bean>
</beans>
複製程式碼
Java Config/註解 方式
掃描的策略需要在xml中配置。 可以指定掃描的包,還可以新增一些過濾器,實現更細緻的掃描策略。 以下四個註解去註解的類都會被掃描並發現為Bean並註冊到IoC容器中。
<context:component-scan base-package="com.tuo.bean"/>
複製程式碼
-
@Component 元註解 用元註解去註解一個註解,這個註解也可以被自動發現 通用註解,可作用於任何bean
-
@Repository 通常用於註解DAO類,即持久層
-
@Service 通常用於註解Service類,即服務層
-
@Controller 通常用於註解Controller類,即控制層(mvc)
@Scope可以註解一個bean指定它的作用域,預設為singleton
還有一些其他的註解可以看原始碼學習, @Configuration
@Bean
@Import
@DependsOn
。
生命週期
定義
初始化
全域性:
<beans ... ... ...
default-init-method="init" default-destroy-method="destroy">
</beans>
複製程式碼
具體類:
- 實現
org.springframework.beans.factory.InitializingBean
介面, 覆蓋afterPropertisSet
方法 - 配置
init-method
方法
使用
銷燬
- 實現
org.springframework.beans.factory.DisposableBean
介面, 覆蓋destory
方法 - 配置
destory-method
方法
自動裝配
自動裝配相較於普通的設值注入和構造注入,xml檔案的bean配置更為簡單,bean定義中也不需要寫set方法/構造方法。
只需在bean中配置Autowiring mode
,或者配置全域性的default-autowire
.
- NO 預設方式,不採取任何檢查
- byName 檢查容器中id與這個bean屬性完全一致的bean,並將其與屬性自動裝配。
- byType
檢查容器中與這個bean屬性型別相同的bean。
- 如果只有一個則與之裝配。
- 如果有多個,則丟擲異常。
- 如果沒有找到,則無事發生。
- Constructor
Resources&ResourceLoader
Resource封裝型別
- URLResource
- ClassPathResource
- FileSystemResource
- ServletContextResource
- InputStreamResource
- ByteArrayResource
ResourceLoader
它是一個介面。
public interface ResourceLoader{
Resource getResource(String location);
}
複製程式碼
spring
中所有application contexts
都實現了這個介面。
都可以當成ResourceLoader
來用。
都可以獲取到Resource
的例項。
字首:
- classpath:
- file:
- http:
- (none) 依賴於Application Context的獲取方式
Autowired等常用註解說明
-
@Required 適用於setter方法上,僅僅表示這個屬性必須在配置的時候填充一個確定值,可以是bean 標籤的配置,也可以是自動裝配。
-
@Autowired 適用於setter方法、構造方法、和成員變數。與
@Requred
效果類似。預設情況下,如果找不到合適的bean來注入屬性,將會導致autowiring失敗並丟擲異常。可以通過
@Autowired(required=false)
來避免.每個類只有一個構造器可以被註解為
@Autowired(required=true)
.@Autowired
的必要屬性建議使用傳統的@Required
.常用於註解那些眾所周知的解析依賴性介面,比如:
BeanFactory
,ApplicationContext
,ResourceLoader
還可以實現陣列或Map的自動注入。
Bean容器context
基礎
-
包依賴:
org.springframework.beans
org.springframework.context
-
核心類:
-
BeanFactory
,提供配置結構和基本功能,載入並初始化Bean -
ApplicationContext
,儲存了Bean物件並在Spring中廣泛使用
-
Bean容器的初始化方式
- 本地檔案
FileSystemXmlAppliactionContext context = new FileSystemXmlAppliactionContext("F:xx/xx.xml")
- Classpath
ClasspathXmlAppliactionContext context = new ClasspathXmlAppliactionContext("classpath:spring-context.xml")
- Web應用中依賴servlet或listener
org.springframework.web.context.ContextLoaderListener/Servlet
IoC/DI
當需要一個物件時,不自己去建立這個物件,而是向spring申請,從IoC容器中拿一個出來用。
實現IoC的方式是依賴注入。
注入
- 設值注入
<property name="injectionDAO" ref="injectionDAO"/>
複製程式碼
通過呼叫類的set方法注入。
- 構造注入
<constructor-arg name="injectionDAO" ref="injectionDAO"/>
複製程式碼
通過呼叫類的建構函式注入。
AOP
通過預編譯方式和執行期動態代理實現程式功能的統一維護的技術。
預編譯: AspectJ
動態代理:JDK動態代理、CGLib
主要功能
- 日誌記錄
- 效能統計
- 安全控制
- 事務處理
- 異常處理
相關概念
-
切面 Aspect:一個關注點的模組化,可能會橫切多個物件
-
連線點 Joinpoint : 程式執行過程中的某個特定的點
-
通知 Advice : 在切面的某個特定的連線點執行的動作
-
切入點 Pointcut: 匹配連線點的斷言,在AOP中通知和一個切入點表示式關聯
-
引入 Introduction:在不修改類程式碼的前提下,為類加新的方法和屬性。可能是藉助預編譯時修改位元組碼,如AspectJ
-
目標物件 Target Object,被一個或多個切面所通知的物件。
-
AOP代理 AOP Proxy:AOP框架建立的物件,用來實現切面契約(aspect contract)(包括通知方法執行等功能)
-
織入 Weaving: 把切面連線到其他的應用程式型別或者物件上,並建立一個被通知的物件,分為:編譯時織入、類載入時織入、執行時織入
通俗理解
AOP主要提供的都是一些和核心業務功能關聯並不大的輔助功能,拿日誌記錄一點來說,只需在適當的位置前/後插入記錄日誌相關的程式碼。那麼每個需要日誌記錄的關鍵點,也就是AOP裡的切入點Pointcut, 都需要前後插入這些程式碼,也就是執行相關的動作(通知 Advice)。這將是很大的工作量。那麼我們可以將這些和核心功能關聯不大的功能,單獨做成模組,這就是一個切面。切面是我們開發中同樣重要的、垂直於核心功能的一個關注點。那麼我們的切面準備好了以後,如何應用於核心業務功能呢? 這就需要用到Spring AOP提供框架來進行合適的引入。主要有以下幾種引入方式:
- AspectJ 修改位元組碼
- CGLib 建立類的子類,也就是裝飾類,覆寫需要通知的類
- JDK 動態代理 基於反射的JAVA API,提供動態代理的相關框架與介面, 只能代理介面和介面集
Spring AOP
代理模式
- 遠端代理
- 動態代理
- 靜態代理
AspectJ
編譯期的AOP,檢查程式碼並匹配連線點與切入點的代價是高昂的,應當儘量定義良好的切入點。
JDK 動態代理
Spring AOP 預設的代理模式,使用JAVA API,使得任何介面(或者介面集)都可以被代理。
CGLib 代理
如果一個業務物件並沒有實現一個介面時使用。
原理:
執行時生成目標類的子類,Spring 配置這個生成的子類委託方法呼叫到原來的目標。體現了裝飾模式,子類來織入通知。
既然是繼承,那麼類的final
方法不能被通知。因為它們不能被覆蓋。