AOP學習筆記
概 念
1. 切面(Aspect)
切面,對象操作過程中的截面。這可能是AOP中最關(guān)鍵的一個術(shù)語。
我們首先來看一個應(yīng)用開發(fā)中常見的切面:用戶權(quán)限檢查。大概只要是完整的應(yīng)用,都
少不了用戶權(quán)限檢查這個模塊,不同身份的用戶可以做什么,不可以做什么,均由這個模塊
加以判定。 而這個模塊調(diào)用的位置通常也比較固定:用戶發(fā)起請求之后, 執(zhí)行業(yè)務(wù)邏輯之前。
針對權(quán)限檢查這一模塊進行分離,我們就得到了一個切面.
切面意義何在?
首先根據(jù)上例,假設(shè)我們實現(xiàn)了一個通用的權(quán)限檢查模塊,那么就可以在這層切面上進
行統(tǒng)一的集中式權(quán)限管理。而業(yè)務(wù)邏輯組件則無需關(guān)心權(quán)限方面的問題。也就是說,通過切
面,我們可以將系統(tǒng)中各個不同層次上的問題隔離開來,實現(xiàn)統(tǒng)一集約式處理。各切面只需
集中于自己領(lǐng)域內(nèi)的邏輯實現(xiàn)。
這一方面使得開發(fā)邏輯更加清晰,專業(yè)化分工更加易于進行;另一方面,由于切面的隔
離,降低了耦合性,我們就可以在不同的應(yīng)用中將各個切面組合使用,從而使得代碼可重用
性大大增強。
2連接點(JoinPoint)
程序運行過程中的某個階段點。如某個方法調(diào)用,或者某個異常被拋出。
3.處理邏輯(Advice)
在某個連接點所采用的處理邏輯
處理邏輯的調(diào)用模式通常有三種:
i. Around
在連接點前后插入預(yù)處理過程和后處理過程。
ii. Before
僅在連接點之前插入預(yù)處理過程。
iii. Throw
在連接點拋出異常時進行異常處理。
4.切點(PointCut)
一系列連接點的集合,它指明處理方式(Advice)將在何時被觸發(fā)。
Dynamic Proxy 與Spring AOP
Dynamic Proxy是JDK 1.3版本中新引入的一種動態(tài)代理機制。它是Proxy模式的一
種動態(tài)實現(xiàn)版本。
代碼:
public class TxHandler implements InvocationHandler {
private Object originalObject;
public Object bind(Object obj) {
this.originalObject = obj;
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
if (!method.getName().startsWith("save")) {
UserTransaction tx = null;
try {
tx = (UserTransaction) (
new InitialContext().lookup("java/tx")
);
result = method.invoke(originalObject, args);
tx.commit();
} catch (Exception ex) {
if (null != tx) {
try {
tx.rollback();
} catch (Exception e) {
}
}
}
} else {
result = method.invoke(originalObject, args);
}
return result;
}
}
在示例代碼中,我們?yōu)樗忻Q以“save”開頭的方法追加了JTA事務(wù)管理。
下面是夏昕老師在客戶培訓過程中編寫的一個Dynamic Proxy based AOP實現(xiàn)示例,非常簡單,有興趣的讀者可以看看。
1、AOPHandler .java
public class AOPHandler implements InvocationHandler {
private static Log logger = LogFactory.getLog(AOPHandler.class);
private List interceptors = null;
private Object originalObject;
/**
* 返回動態(tài)代理實例
* @param obj
* @return
*/
public Object bind(Object obj) {
this.originalObject = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj
.getClass().getInterfaces(), this);
}
/**
* 在Invoke方法中,加載對應(yīng)的Interceptor,并進行
* 預(yù)處理(before)、后處理(after)以及異常處理(exceptionThrow)過程
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
Throwable ex = null;
InvocationInfo invInfo = new InvocationInfo(proxy, method, args,
result, ex);
logger.debug("Invoking Before Intercetpors!");
invokeInterceptorsBefore(invInfo);
try {
logger.debug("Invoking Proxy Method!");
result = method.invoke(originalObject, args);
invInfo.setResult(result);
logger.debug("Invoking After Method!");
invokeInterceptorsAfter(invInfo);
} catch (Throwable tr) {
invInfo.setException(tr);
logger.debug("Invoking exceptionThrow Method!");
invokeInterceptorsExceptionThrow(invInfo);
throw new AOPRuntimeException(tr);
}
return result;
}
/**
* 加載Interceptor
* @return
*/
private synchronized List getIntercetors() {
if (null == interceptors) {
interceptors = new ArrayList();
//Todo:讀取配置,加載Interceptor實例
//interceptors.add(new MyInterceptor());
}
return interceptors;
}
/**
* 執(zhí)行預(yù)處理方法
* @param invInfo
*/
private void invokeInterceptorsBefore(InvocationInfo invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
for (int i = 0; i < len; i++) {
((Interceptor) interceptors.get(i)).before(invInfo);
}
}
/**
* 執(zhí)行后處理方法
* @param invInfo
*/
private void invokeInterceptorsAfter(InvocationInfo invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
for (int i = len - 1; i >= 0; i--) {
((Interceptor) interceptors.get(i)).after(invInfo);
}
}
/**
* 執(zhí)行異常處理方法
* @param invInfo
*/
private void invokeInterceptorsExceptionThrow(InvocationInfo
invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
for (int i = len - 1; i >= 0; i--) {
((Interceptor)
interceptors.get(i)).exceptionThrow(invInfo);
}
}
}
2、Interceptor .java:
public interface Interceptor {
public void before(InvocationInfo invInfo);
public void after(InvocationInfo invInfo);
public void exceptionThrow(InvocationInfo invInfo);
}
3、InvocationInfo.java:
public class InvocationInfo {
Object proxy;
Method method;
Object[] args;
Object result;
Throwable Exception;
public InvocationInfo(Object proxy, Method method, Object[] args,
Object result, Throwable exception) {
super();
this.proxy = proxy;
this.method = method;
this.args = args;
this.result = result;
Exception = exception;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public Throwable getException() {
return Exception;
}
public void setException(Throwable exception) {
Exception = exception;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public Object getProxy() {
return proxy;
}
public void setProxy(Object proxy) {
this.proxy = proxy;
}
}
4、AOPFactory.java
public class AOPFactory {
private static Log logger = LogFactory.getLog(AOPFactory.class);
/**
* 根據(jù)類名創(chuàng)建類實例
* @param clzName
* @return
* @throws ClassNotFoundException
*/
public static Object getClassInstance(String clzName){
Class cls;
try {
cls = Class.forName(clzName);
return (Object)cls.newInstance();
} catch (ClassNotFoundException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
} catch (InstantiationException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
} catch (IllegalAccessException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
}
}
/**
* 根據(jù)傳入的類名,返回AOP代理對象
* @param clzName
* @return
*/
public static Object getAOPProxyedObject(String clzName){
AOPHandler txHandler = new AOPHandler();
Object obj = getClassInstance(clzName);
return txHandler.bind(obj);
}
}
5、MyInterceptor .java
public class MyInterceptor implements Interceptor{
private static Log logger = LogFactory.getLog(MyInterceptor.class);
public void before(InvocationInfo invInfo) {
logger.debug("Pre-processing");
}
public void after(InvocationInfo invInfo) {
logger.debug("Post-processing");
}
public void exceptionThrow(InvocationInfo invInfo) {
logger.debug("Exception-processing");
}
}
posted on 2009-03-25 11:09
重慶理工小子 閱讀(318)
評論(0) 編輯 收藏 所屬分類:
Spring2