AOP學(xué)習(xí)筆記
概 念
1. 切面(Aspect)
切面,對(duì)象操作過程中的截面。這可能是AOP中最關(guān)鍵的一個(gè)術(shù)語(yǔ)。
我們首先來看一個(gè)應(yīng)用開發(fā)中常見的切面:用戶權(quán)限檢查。大概只要是完整的應(yīng)用,都
少不了用戶權(quán)限檢查這個(gè)模塊,不同身份的用戶可以做什么,不可以做什么,均由這個(gè)模塊
加以判定。 而這個(gè)模塊調(diào)用的位置通常也比較固定:用戶發(fā)起請(qǐng)求之后, 執(zhí)行業(yè)務(wù)邏輯之前。
針對(duì)權(quán)限檢查這一模塊進(jìn)行分離,我們就得到了一個(gè)切面.
切面意義何在?
首先根據(jù)上例,假設(shè)我們實(shí)現(xiàn)了一個(gè)通用的權(quán)限檢查模塊,那么就可以在這層切面上進(jìn)
行統(tǒng)一的集中式權(quán)限管理。而業(yè)務(wù)邏輯組件則無需關(guān)心權(quán)限方面的問題。也就是說,通過切
面,我們可以將系統(tǒng)中各個(gè)不同層次上的問題隔離開來,實(shí)現(xiàn)統(tǒng)一集約式處理。各切面只需
集中于自己領(lǐng)域內(nèi)的邏輯實(shí)現(xiàn)。
這一方面使得開發(fā)邏輯更加清晰,專業(yè)化分工更加易于進(jìn)行;另一方面,由于切面的隔
離,降低了耦合性,我們就可以在不同的應(yīng)用中將各個(gè)切面組合使用,從而使得代碼可重用
性大大增強(qiáng)。
2連接點(diǎn)(JoinPoint)
程序運(yùn)行過程中的某個(gè)階段點(diǎn)。如某個(gè)方法調(diào)用,或者某個(gè)異常被拋出。
3.處理邏輯(Advice)
在某個(gè)連接點(diǎn)所采用的處理邏輯
處理邏輯的調(diào)用模式通常有三種:
i. Around
在連接點(diǎn)前后插入預(yù)處理過程和后處理過程。
ii. Before
僅在連接點(diǎn)之前插入預(yù)處理過程。
iii. Throw
在連接點(diǎn)拋出異常時(shí)進(jìn)行異常處理。
4.切點(diǎn)(PointCut)
一系列連接點(diǎn)的集合,它指明處理方式(Advice)將在何時(shí)被觸發(fā)。
Dynamic Proxy 與Spring AOP
Dynamic Proxy是JDK 1.3版本中新引入的一種動(dòng)態(tài)代理機(jī)制。它是Proxy模式的一
種動(dòng)態(tài)實(shí)現(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ù)管理。
下面是夏昕老師在客戶培訓(xùn)過程中編寫的一個(gè)Dynamic Proxy based AOP實(shí)現(xiàn)示例,非常簡(jiǎn)單,有興趣的讀者可以看看。
1、AOPHandler .java
public class AOPHandler implements InvocationHandler {
private static Log logger = LogFactory.getLog(AOPHandler.class);
private List interceptors = null;
private Object originalObject;
/**
* 返回動(dòng)態(tài)代理實(shí)例
* @param obj
* @return
*/
public Object bind(Object obj) {
this.originalObject = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj
.getClass().getInterfaces(), this);
}
/**
* 在Invoke方法中,加載對(duì)應(yīng)的Interceptor,并進(jìn)行
* 預(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實(shí)例
//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)建類實(shí)例
* @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代理對(duì)象
* @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");
}
}