上篇《spring aop實(shí)例之xml配置》中,講解了xml配置方式,今天來說說aspectj注解方式去配置spring aop。
依舊采用的jdk代理,接口和實(shí)現(xiàn)類代碼請參考上篇博文。主要是將aspect類分享一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
package com.tgb.aop; import org.aspectj.lang.joinpoint; import org.aspectj.lang.proceedingjoinpoint; import org.aspectj.lang.annotation.after; import org.aspectj.lang.annotation.afterreturning; import org.aspectj.lang.annotation.afterthrowing; import org.aspectj.lang.annotation.around; import org.aspectj.lang.annotation.aspect; import org.aspectj.lang.annotation.before; import org.aspectj.lang.annotation.declareparents; import org.aspectj.lang.annotation.pointcut; /** * 測試after,before,around,throwing,returning advice. * @author admin * */ @aspect public class aspcejadvice { /** * pointcut * 定義pointcut,pointcut的名稱為aspectjmethod(),此方法沒有返回值和參數(shù) * 該方法就是一個(gè)標(biāo)識,不進(jìn)行調(diào)用 */ @pointcut ( "execution(* find*(..))" ) private void aspectjmethod(){}; /** * before * 在核心業(yè)務(wù)執(zhí)行前執(zhí)行,不能阻止核心業(yè)務(wù)的調(diào)用。 * @param joinpoint */ @before ( "aspectjmethod()" ) public void beforeadvice(joinpoint joinpoint) { system.out.println( "-----beforeadvice().invoke-----" ); system.out.println( " 此處意在執(zhí)行核心業(yè)務(wù)邏輯前,做一些安全性的判斷等等" ); system.out.println( " 可通過joinpoint來獲取所需要的內(nèi)容" ); system.out.println( "-----end of beforeadvice()------" ); } /** * after * 核心業(yè)務(wù)邏輯退出后(包括正常執(zhí)行結(jié)束和異常退出),執(zhí)行此advice * @param joinpoint */ @after (value = "aspectjmethod()" ) public void afteradvice(joinpoint joinpoint) { system.out.println( "-----afteradvice().invoke-----" ); system.out.println( " 此處意在執(zhí)行核心業(yè)務(wù)邏輯之后,做一些日志記錄操作等等" ); system.out.println( " 可通過joinpoint來獲取所需要的內(nèi)容" ); system.out.println( "-----end of afteradvice()------" ); } /** * around * 手動控制調(diào)用核心業(yè)務(wù)邏輯,以及調(diào)用前和調(diào)用后的處理, * * 注意:當(dāng)核心業(yè)務(wù)拋異常后,立即退出,轉(zhuǎn)向afteradvice * 執(zhí)行完afteradvice,再轉(zhuǎn)到throwingadvice * @param pjp * @return * @throws throwable */ @around (value = "aspectjmethod()" ) public object aroundadvice(proceedingjoinpoint pjp) throws throwable { system.out.println( "-----aroundadvice().invoke-----" ); system.out.println( " 此處可以做類似于before advice的事情" ); //調(diào)用核心邏輯 object retval = pjp.proceed(); system.out.println( " 此處可以做類似于after advice的事情" ); system.out.println( "-----end of aroundadvice()------" ); return retval; } /** * afterreturning * 核心業(yè)務(wù)邏輯調(diào)用正常退出后,不管是否有返回值,正常退出后,均執(zhí)行此advice * @param joinpoint */ @afterreturning (value = "aspectjmethod()" , returning = "retval" ) public void afterreturningadvice(joinpoint joinpoint, string retval) { system.out.println( "-----afterreturningadvice().invoke-----" ); system.out.println( "return value: " + retval); system.out.println( " 此處可以對返回值做進(jìn)一步處理" ); system.out.println( " 可通過joinpoint來獲取所需要的內(nèi)容" ); system.out.println( "-----end of afterreturningadvice()------" ); } /** * 核心業(yè)務(wù)邏輯調(diào)用異常退出后,執(zhí)行此advice,處理錯(cuò)誤信息 * * 注意:執(zhí)行順序在around advice之后 * @param joinpoint * @param ex */ @afterthrowing (value = "aspectjmethod()" , throwing = "ex" ) public void afterthrowingadvice(joinpoint joinpoint, exception ex) { system.out.println( "-----afterthrowingadvice().invoke-----" ); system.out.println( " 錯(cuò)誤信息:" +ex.getmessage()); system.out.println( " 此處意在執(zhí)行核心業(yè)務(wù)邏輯出錯(cuò)時(shí),捕獲異常,并可做一些日志記錄操作等等" ); system.out.println( " 可通過joinpoint來獲取所需要的內(nèi)容" ); system.out.println( "-----end of afterthrowingadvice()------" ); } } |
application-config.xml中,只需要配置業(yè)務(wù)邏輯bean和aspect bean,并啟用aspect注解即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?xml version= "1.0" encoding= "utf-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/xmlschema-instance" xmlns:aop= "http://www.springframework.org/schema/aop" xmlns:tx= "http://www.springframework.org/schema/tx" xsi:schemalocation="http: //www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http: //www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http: //www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- 啟用aspectj對annotation的支持 --> <aop:aspectj-autoproxy/> <bean id= "usermanager" class = "com.tgb.aop.usermanagerimpl" /> <bean id= "aspcejhandler" class = "com.tgb.aop.aspcejadvice" /> </beans> |
結(jié)果如圖:
通過測試的發(fā)現(xiàn)aroundadvice、beforeadvice、afteradvice、returningadvice的執(zhí)行順序是根據(jù)注解的順序而定的。但是有時(shí)候修改了順序,結(jié)果卻沒有變化,可能是緩存的緣故。前幾天我也遇到了這樣的問題,不過今天再測試了一下,發(fā)現(xiàn)執(zhí)行順序又跟注解的順序一致了。
xml 和 annotation 注解都可以作為配置項(xiàng),對spring aop進(jìn)行配置管理,那么它們各自都有什么優(yōu)缺點(diǎn)呢?
首先說說 xml 。目前 web 應(yīng)用中幾乎都使用 xml 作為配置項(xiàng),例如我們常用的框架 struts、spring、hibernate 等等都采用 xml 作為配置。xml 之所以這么流行,是因?yàn)樗暮芏鄡?yōu)點(diǎn)是其它技術(shù)的配置所無法替代的:
- xml 作為可擴(kuò)展標(biāo)記語言最大的優(yōu)勢在于開發(fā)者能夠?yàn)檐浖可矶ㄖ七m用的標(biāo)記,使代碼更加通俗易懂。
- 利用 xml 配置能使軟件更具擴(kuò)展性。例如 spring 將 class 間的依賴配置在 xml 中,最大限度地提升應(yīng)用的可擴(kuò)展性。
- 具有成熟的驗(yàn)證機(jī)制確保程序正確性。利用 schema 或 dtd 可以對 xml 的正確性進(jìn)行驗(yàn)證,避免了非法的配置導(dǎo)致應(yīng)用程序出錯(cuò)。
- 修改配置而無需變動現(xiàn)有程序。
雖然有如此多的好處,但畢竟沒有什么萬能的東西,xml 也有自身的缺點(diǎn)。
- 需要解析工具或類庫的支持。
- 解析 xml 勢必會影響應(yīng)用程序性能,占用系統(tǒng)資源。
- 配置文件過多導(dǎo)致管理變得困難。
- 編譯期無法對其配置項(xiàng)的正確性進(jìn)行驗(yàn)證,或要查錯(cuò)只能在運(yùn)行期。
- ide 無法驗(yàn)證配置項(xiàng)的正確性無能為力。
- 查錯(cuò)變得困難。往往配置的一個(gè)手誤導(dǎo)致莫名其妙的錯(cuò)誤。
- 開發(fā)人員不得不同時(shí)維護(hù)代碼和配置文件,開發(fā)效率變得低下。
- 配置項(xiàng)與代碼間存在潛規(guī)則。改變了任何一方都有可能影響另外一方。
讓我們來看看 annotation 的優(yōu)點(diǎn)。
- 保存在 class 文件中,降低維護(hù)成本。
- 無需工具支持,無需解析。
- 編譯期即可驗(yàn)證正確性,查錯(cuò)變得容易。
- 提升開發(fā)效率。
同樣 annotation 也不是萬能的,它也有很多缺點(diǎn)。
- 若要對配置項(xiàng)進(jìn)行修改,不得不修改 java 文件,重新編譯打包應(yīng)用。
- 配置項(xiàng)編碼在 java 文件中,可擴(kuò)展性差。
總結(jié):沒有一個(gè)事物是萬能的,同樣 xml 和 java annotation 都有各自的優(yōu)缺點(diǎn)。通過以上對比,細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn)它們的優(yōu)缺點(diǎn)恰恰是互補(bǔ)的。xml 的強(qiáng)項(xiàng)是 annotation 所不具備的,而 annotation 的優(yōu)勢也是 xml 所欠缺的。這也正是時(shí)下流行的 xml + annotation 配置的原因所在。平衡才是王道呀!
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://blog.csdn.net/xiaoxian8023/article/details/17285809