Spring技術(shù)手冊(cè)筆記(二):Spring AOP
Posted on 2009-11-08 20:12 codingliyi 閱讀(605) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): Java EE四、SpringAOP
學(xué)習(xí)AOP必須首先要學(xué)習(xí)代理模式。詳見(jiàn)我的上一篇筆記:AOP基礎(chǔ):動(dòng)態(tài)代理
AOP觀念與術(shù)語(yǔ)
1.橫切關(guān)注點(diǎn)(Cross-cutting concern)
類(lèi)似于日志記錄、安全檢查、事務(wù)等系統(tǒng)層面的服務(wù),在一些應(yīng)用程序中常被尖刀安插至各個(gè)對(duì)象的處理流程中,這些動(dòng)作在AOP術(shù)語(yǔ)中被稱(chēng)為橫切關(guān)注點(diǎn)。
2.切面(Aspect)
將散落于各個(gè)業(yè)務(wù)對(duì)象中的橫切關(guān)注點(diǎn)(如日志記錄)收集起來(lái),設(shè)計(jì)各個(gè)獨(dú)立可重用的對(duì)象,這些對(duì)象被稱(chēng)為切面。如上篇筆記中的Handler類(lèi)。在需要該服務(wù)時(shí),織入(Weave)應(yīng)用程序之上。
3.Advice
Aspect的具體實(shí)現(xiàn)被稱(chēng)之為Advice。例如,Advice中會(huì)包括日志記錄程序代碼是如何實(shí)現(xiàn)的。Advice中包含了橫切關(guān)注點(diǎn)的行為或提供的服務(wù)。
4.Joinpoint
Aspect在應(yīng)用程序執(zhí)行時(shí)加入業(yè)務(wù)流程的點(diǎn)或時(shí)機(jī)。這個(gè)時(shí)機(jī)可能是某個(gè)方法執(zhí)行之前或之后或兩者都有,或是某個(gè)異常發(fā)生的時(shí)候。
5.Pointcut
Pointcut是一個(gè)定義,可在某個(gè)定義文件中編寫(xiě)Pointcut,指定某個(gè)Aspect在哪些Joinpoint時(shí)被織入。
Spring AOP
Spring的Advice是在執(zhí)行時(shí)期導(dǎo)入至Targets的,可以讓Target實(shí)現(xiàn)預(yù)先定義的接口,則Spring在執(zhí)行時(shí)會(huì)使用動(dòng)態(tài)代理;如不實(shí)現(xiàn)接口,則會(huì)使用CGLIB為Target產(chǎn)生一個(gè)子類(lèi)作為代理類(lèi)。
Spring只支持方法的Joinpoints,即Advices將在方法執(zhí)行的前后調(diào)用。
Advices
Advices包括Aspect的真正邏輯,具體說(shuō)來(lái)就是一個(gè)類(lèi),由于織入至Targets的時(shí)機(jī)不同,Spring提供了幾種不同的Advices,如BeforeAdvice、AfterAdvice、ArountAdvice、ThrowAdvice。
BeforeAdvice
通過(guò)實(shí)現(xiàn)org.springframework.aop.MethodBeforeAdvice接口來(lái)實(shí)現(xiàn)邏輯。
該接口定義如下方法:
public void before(Method method, Object[] args, Object target)
throws Throwable;
Before()方法聲明為void,所以不用回傳任何結(jié)果,在before()執(zhí)行完畢之后,除非拋出異常,否則目標(biāo)對(duì)象上的方法就會(huì)被執(zhí)行。
示例代碼如下:

2

3

4

5


6

7


2

3

4

5

6

7

8

9

10

11

12

AfterAdvice
通過(guò)實(shí)現(xiàn)org.springframework.aop.AfterReturningAdvice接口來(lái)實(shí)現(xiàn)。
該接口定義如下方法:
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
示例代碼類(lèi)似于BeforeAdvice。
AroundAdvice
通過(guò)實(shí)現(xiàn)org.aopalliance.intercept.MethodIntercept接口來(lái)實(shí)現(xiàn)。
該接口定義如下方法:
public Object invoke(MethodInvocation methodInvocation) throws Throwable;
示例代碼如下:

2

3

4

5

6


7

8


9

10

11

ThrowAdvice
通過(guò)實(shí)現(xiàn)org.springframework.aop.ThrowAdvice接口來(lái)實(shí)現(xiàn)。
該接口只是個(gè)標(biāo)簽接口,沒(méi)有任何方法。可以定義任意方法名稱(chēng),只要是如下形式:
methodName([Method], [args], [target], subclassOfThrowable);
其中[]表示可選。subclassOfThrowable必須是Throwable的子類(lèi)。當(dāng)異常發(fā)生時(shí),會(huì)檢驗(yàn)所設(shè)定的Throw Advice中是否有符合異常類(lèi)型的方法,如有則執(zhí)行。
注意:當(dāng)異常發(fā)生時(shí),ThrowAdvice的任務(wù)只是執(zhí)行對(duì)應(yīng)的方法,并不能處理異常。當(dāng)其執(zhí)行完畢后,原來(lái)的異常仍被傳播至應(yīng)用程序之中。
Pointcut與Advisor
在Spring中,可以指定更精細(xì)的織入時(shí)機(jī),Pointcut定義了Advice的應(yīng)用時(shí)機(jī),在Spring中,使用PointcutAdvisor將Pointcut與Advice結(jié)合成一個(gè)對(duì)象。Spring內(nèi)建的Pointcut都有對(duì)應(yīng)的PointcutAdvisor。

2

3

4

5

6

7

NameMatchMethodPointcutAdvisor
這是最基本的PointcutAdvisor。可以指定所要應(yīng)用的目標(biāo)上的方法名稱(chēng)。
示例代碼:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

Autoproxy
自動(dòng)代理可以不用為每一個(gè)目標(biāo)對(duì)象手動(dòng)定義代理對(duì)象,使用自動(dòng)代理,可以透過(guò)Bean名稱(chēng)或是Pointcut的比對(duì),自動(dòng)為符合比對(duì)條件的目標(biāo)對(duì)象建立代理對(duì)象。
BeanNameAutoProxyCreator
當(dāng)應(yīng)用程序很大時(shí),可以為目標(biāo)對(duì)象取好適當(dāng)?shù)?font face="Courier New">Bean名稱(chēng),例如xxxService。此時(shí)可修改Bean定義文件如下:

2

3

4

5

6

7

8

9

10

11

12
