2013年11月16日 星期六

AspectJ Annotations用法小歸納

近日有機會玩到利用AspectJ在Spring框架中達到AOP,

因此想要記錄一點小小的心得,

首先設定可參考Mkyong大大的教學文章,將AspectJ導入Spring專案中,

文章連結:http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/

再來重點是實際怎麼使用,其實Mkyong的文章也寫得很詳細了XD


AspectJ訂定的切入點有以下幾種

@Before:在method執行之前會先執行此段程式

@After:在method執行完後會執行此段程式

@AfterReturning:在method執行完並且有成功return時會執行此段程式

@AfterThrowing:在method執行中拋出Exception時會執行此段程式

@Around:囊括以上四種狀態,可控制從進入method前到離開method後的所有階段,
     類似filter的概念,filter之於servlet就像@Around之於method,
     除此之外還有一個特色是可取得並修改method的return值

如果以上敘述很抽象,就讓程式碼說話吧,

myMethod()表示原本要執行的程式,doXxxAOP()表示不同方式的AOP切入位置:
doBeforeAOP();
try {
    Throwable throwMe = null;
    try {
        myMethod();
    } catch(Throwable catchMe)(
        throwMe = catchMe;
    } finally {
        doAfterAOP();
    }
    if(throwMe != null)
        throw throwMe;
    doAfterReturningAOP();
} catch(Throwable throwMe) {
    doAfterThrowingAOP();
    throw throwMe;
}

上面的程式碼示意了各切入點觸發條件和執行的時間先後順序,

( 純粹由我的使用心得整理的大致概念,AOP的原碼並不是長這樣 )

除了@AfterReturning和@AfterThrowing是有條件性的觸發以外,

@Before和@After都是無論如何都會執行到的。



除了以上四種標準的Annotation外,AspectJ也提供了客製化的空間──@Around

@Around非常強大,從進入method前到離開method後的所有流程都可以重新定義,

有點像是使用filter的概念,

以下是一段簡單的範例就可以了解他的用法
@Around("execution(* com.mrnine.aop.Foo.aroundTest(..))")
public String doAroundTest(ProceedingJoinPoint joinPoint) throws Throwable {
    String result = (String) joinPoint.proceed();
    result = "Hello! "+result;
    return result;
}

由以上範例可知,使用@Around時

要在甚麼時間點呼叫 myMethod() 是取決於呼叫 procceed() 的時間,

因此我們可以在呼叫 procceed() 前增加任何我們需要的前處理,

而 procceed() 的 return 值就是 myMethod()的 return 值,

我們也可以直接修改這個 return 值,修改後再往外送,

如範例所示,經過Around AOP的 return 字串前面都會多串一個 Hello! 字樣



熟悉以上五種武器的觀念後,

實戰的部分就直接看前文提到的Mkyong大大的詳細範例吧!

沒有留言:

張貼留言