1. 程式人生 > 程式設計 >Spring入門之初識IoC和AOP

Spring入門之初識IoC和AOP

Bean

配置

配置好的bean可以直接通過spring的上下文獲取。 而配置只用告訴spring,一個xml檔案的路徑,spring就會基於這個xml生成一個對應的context物件。 類似 Bean b = context.getBean("Bean.id").

配置項

  • id 唯一標識

  • class 具體要例項化的類

  • scope 範圍/作用域

  1. singleton 一個Bean容器只存在一份,但是可以基於一份xml檔案生成兩個context,這兩個context容器可以有各自的單例物件
  2. prototype 每次請求/使用時建立新的例項,destroy不生效,自動回收
  3. request 每次http請求
    建立一個例項且只在這個request有效
  4. session
  5. 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"/>
複製程式碼
  1. @Component 元註解 用元註解去註解一個註解,這個註解也可以被自動發現 通用註解,可作用於任何bean

  2. @Repository 通常用於註解DAO類,即持久層

  3. @Service 通常用於註解Service類,即服務層

  4. @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.

  1. NO 預設方式,不採取任何檢查
  2. byName 檢查容器中id與這個bean屬性完全一致的bean,並將其與屬性自動裝配。
  3. byType 檢查容器中與這個bean屬性型別相同的bean。
    • 如果只有一個則與之裝配。
    • 如果有多個,則丟擲異常。
    • 如果沒有找到,則無事發生。
  4. 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

基礎

  1. 包依賴:

    • org.springframework.beans
    • org.springframework.context
  2. 核心類:

    • 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的方式是依賴注入。

注入

  1. 設值注入
<property name="injectionDAO" ref="injectionDAO"/>
複製程式碼

通過呼叫類的set方法注入。

  1. 構造注入
<constructor-arg name="injectionDAO" ref="injectionDAO"/>
複製程式碼

通過呼叫類的建構函式注入。

AOP

通過預編譯方式執行期動態代理實現程式功能的統一維護的技術。

預編譯: AspectJ

動態代理:JDK動態代理CGLib

主要功能

  1. 日誌記錄
  2. 效能統計
  3. 安全控制
  4. 事務處理
  5. 異常處理

相關概念

  • 切面 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

代理模式

  1. 遠端代理
  2. 動態代理
  3. 靜態代理

AspectJ

編譯期的AOP,檢查程式碼並匹配連線點與切入點的代價是高昂的,應當儘量定義良好的切入點。

JDK 動態代理

Spring AOP 預設的代理模式,使用JAVA API,使得任何介面(或者介面集)都可以被代理。

CGLib 代理

如果一個業務物件並沒有實現一個介面時使用。

原理: 執行時生成目標類的子類,Spring 配置這個生成的子類委託方法呼叫到原來的目標。體現了裝飾模式,子類來織入通知。 既然是繼承,那麼類的final方法不能被通知。因為它們不能被覆蓋