1. 程式人生 > >spring事務切面對織入自定義鎖服務的啟示

spring事務切面對織入自定義鎖服務的啟示

1、AOP是什麼?

AOP面向切面程式設計,有個重要概念闡述:  切面

切面:  切入點 通知 ,切面就類似於日常生活中的鬧鐘,包括鐘點和鐘聲;

切入點: 業務元件的粒度,譬如類的方法\POJO

通知:   執行切入點,需要裝飾的方式,類似於裝飾器模式

2SpringAOP基礎

SpringAOP的核心是動態代理,就是在動態代理類中織入一些需要處理的邏輯. Spring框架主要使用JDK動態代理和CGLIB,這兩種分別針對不同的應用場景,除非顯示配置,一般由Spring自己負責動態切換.

2.1)JDK動態代理 建立一個實現目標物件的所有介面的代理類,並在代理類中織入配置切面攔截器,所以需要代理物件實現介面

;

2.2)CGLIB 建立代理物件的一個子類,在子類中代理父類的所有方法,並織入切面攔截器.

3、Spring中事務切面原理

   3.1)SpringAOP在框架執行流程,如圖

   

 其實就是一個遞迴呼叫的過程,在每個切面攔截器的前半部分執行完畢後,去呼叫後攔截器鏈的下一個攔截器,最後執行到目標物件(代理物件),依次返回,順次執行攔截器的後半部分,所以Spring的事務管理就是這樣的實現的,如圖

                                                                                               

執行事務切面的前半部分,獲取事務資源,然後執行其他攔截器和目標物件(一般就是我們業務方法CRUD),目標物件執行完畢,遞迴呼叫返回,到達攔截器事務切面後半部分,如果異常,回滾事務,否則提交事務,最後釋放事務資源,原始碼分析如下:

1、JDK動態代理器

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable

其中這個方法是動態代理核心方法,對應的代理物件被執行時,代理類會呼叫該方法,而該方法中 反射方法處理器會發起對切面攔截器鏈的遞迴呼叫


2、反射方法處理器

org.springframework

.aop.framework.ReflectiveMethodInvocation

1、事務切面攔截器

(我們的所服務可以參考他的實現方法來做的),原始碼如下圖

分析一下織入事務管理的方法,你會恍然大悟,沒錯,Spring就是為業務元件這樣管理事務的


1、設計一個為給定業務元件織入鎖服務的方案

  1)設計一個鎖服務切面 如檔案 LockServiceAspect.java(仿照事務切面設計)

  2)xml檔案配置鎖服務的切面,如下

這裡有個細節問題,就是事務切面和lock切面的優先順序問題,如圖(Lock優先順序高)


此種情況: 執行業務方法時,spring框架先獲取鎖資源,如果鎖沒有獲取成功,事務資源不會佔用,這種方案的優勢: 1)單機事務受分散式鎖保護,不會出現多節點操作資料不一致;2)鎖如果未獲取成功,不會佔用鎖資源.劣勢:如果事務執行時間過長,鎖可能超時,此時事務不受鎖保護,可能造成分散式下資料操作的不一致(建議設定鎖超時時間大於事務超時時間)

另一種情況,事務優先順序高


優勢: 始終保障單機事務的方法受分散式鎖的保護

劣勢: 如果鎖大量超時,就會造成,大量事務資源被佔用

切面優先順序配置:




鎖服務切面的實現類 如下:

/**
 * 鎖服務切面攔截器
 * @author Administrator
 *
 */
public class LockServiceAspect {

public Object invoke(final ProceedingJoinPoint pjp) {
return invokeWithLock(pjp, new InvocationCallback() {
public Object proceedWidhInvocation(ProceedingJoinPoint pjp) throws Throwable {
return pjp.proceed();
}
});
}

/**
* 織入Lock服務管理
* @param callback
* @return
*/
private Object invokeWithLock(final ProceedingJoinPoint pjp, InvocationCallback callback) {
Object result = null;
//獲取鎖
try {
result = callback.proceedWidhInvocation(pjp);
}catch(Throwable e){
//異常處理
}finally{
//釋放鎖
}
return result;
}

/**
* 方法反射處理器回撥介面
* @author Administrator
*
*/
protected interface InvocationCallback {
public Object proceedWidhInvocation(ProceedingJoinPoint pjp) throws Throwable;
}
}