前言
在之前的一篇文章中我們講到spring的xml實(shí)現(xiàn),這里我們講講使用注解如何實(shí)現(xiàn)aop呢。前面已經(jīng)講過(guò)aop的簡(jiǎn)單理解了,這里就不在贅述了。話不多說(shuō),來(lái)一起看看詳細(xì)的介紹:
注解方式實(shí)現(xiàn)aop我們主要分為如下幾個(gè)步驟:
1.在切面類(lèi)(為切點(diǎn)服務(wù)的類(lèi))前用@Aspect注釋修飾,聲明為一個(gè)切面類(lèi)。
2.用@Pointcut注釋聲明一個(gè)切點(diǎn),目的是為了告訴切面,誰(shuí)是它的服務(wù)對(duì)象。(此注釋修飾的方法的方法體為空,不需要寫(xiě)功能比如 public void say(){};
就可以了,方法名可以被候命的具體服務(wù)功能所以引用,它可以被理解為切點(diǎn)對(duì)象的一個(gè)代理對(duì)象方法)
3.在對(duì)應(yīng)的方法前用對(duì)應(yīng)的通知類(lèi)型注釋修飾,將對(duì)應(yīng)的方法聲明稱(chēng)一個(gè)切面功能,為了切點(diǎn)而服務(wù)
4.在spring配置文件中開(kāi)啟aop注釋自動(dòng)代理。如: <aop:aspectj-autoproxy/>
這樣講可能還是很抽象,那么,廢話不多說(shuō),我們代碼說(shuō)話,代碼如下:
騎士類(lèi):(看過(guò)上一篇內(nèi)容的就知道騎士是什么東西了,嘿嘿嘿)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package com.cjh.aop2; import org.springframework.stereotype.Component; /** * @author Caijh * * 2017年7月11日 下午3:53:19 */ @Component ( "knight" ) public class BraveKnight { public void saying(){ System.out.println( "我是騎士..(切點(diǎn)方法)" ); } } |
切面類(lèi):(注釋主要在這里體現(xiàn))
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
|
package com.cjh.aop2; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * @author Caijh * email:[email protected] * 2017年7月12日 上午9:31:43 */ /** * 注解方式聲明aop * 1.用@Aspect注解將類(lèi)聲明為切面(如果用@Component("")注解注釋為一個(gè)bean對(duì)象,那么就要在spring配置文件中開(kāi)啟注解掃描,<context:component-scan base-package="com.cjh.aop2"/> * 否則要在spring配置文件中聲明一個(gè)bean對(duì)象) * 2.在切面需要實(shí)現(xiàn)相應(yīng)方法的前面加上相應(yīng)的注釋?zhuān)簿褪峭ㄖ?lèi)型。 * 3.此處有環(huán)繞通知,環(huán)繞通知方法一定要有ProceedingJoinPoint類(lèi)型的參數(shù)傳入,然后執(zhí)行對(duì)應(yīng)的proceed()方法,環(huán)繞才能實(shí)現(xiàn)。 */ @Component ( "annotationTest" ) @Aspect public class AnnotationTest { //定義切點(diǎn) @Pointcut ( "execution(* *.saying(..))" ) public void sayings(){} /** * 前置通知(注解中的sayings()方法,其實(shí)就是上面定義pointcut切點(diǎn)注解所修飾的方法名,那只是個(gè)代理對(duì)象,不需要寫(xiě)具體方法, * 相當(dāng)于xml聲明切面的id名,如下,相當(dāng)于id="embark",用于供其他通知類(lèi)型引用) * <aop:config> <aop:aspect ref="mistrel"> <!-- 定義切點(diǎn) --> <aop:pointcut expression="execution(* *.saying(..))" id="embark"/> <!-- 聲明前置通知 (在切點(diǎn)方法被執(zhí)行前調(diào)用) --> <aop:before method="beforSay" pointcut-ref="embark"/> <!-- 聲明后置通知 (在切點(diǎn)方法被執(zhí)行后調(diào)用) --> <aop:after method="afterSay" pointcut-ref="embark"/> </aop:aspect> </aop:config> */ @Before ( "sayings()" ) public void sayHello(){ System.out.println( "注解類(lèi)型前置通知" ); } //后置通知 @After ( "sayings()" ) public void sayGoodbey(){ System.out.println( "注解類(lèi)型后置通知" ); } //環(huán)繞通知。注意要有ProceedingJoinPoint參數(shù)傳入。 @Around ( "sayings()" ) public void sayAround(ProceedingJoinPoint pjp) throws Throwable{ System.out.println( "注解類(lèi)型環(huán)繞通知..環(huán)繞前" ); pjp.proceed(); //執(zhí)行方法 System.out.println( "注解類(lèi)型環(huán)繞通知..環(huán)繞后" ); } } |
spring配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<? 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:context = "http://www.springframework.org/schema/context" xmlns:aop = "http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 開(kāi)啟注解掃描 --> < context:component-scan base-package = "com.cjh.aop2" /> <!-- 開(kāi)啟aop注解方式,此步驟s不能少,這樣java類(lèi)中的aop注解才會(huì)生效 --> < aop:aspectj-autoproxy /> </ beans > |
測(cè)試代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.cjh.aop2; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * * @author Caijh * email:[email protected] * 2017年7月11日 下午6:27:06 */ public class Test { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext( "com/cjh/aop2/beans.xml" ); BraveKnight br = (BraveKnight) ac.getBean( "knight" ); br.saying(); } } |
運(yùn)行結(jié)果:
注解類(lèi)型環(huán)繞通知..環(huán)繞前
注解類(lèi)型前置通知
我是騎士..(切點(diǎn)方法)
注解類(lèi)型環(huán)繞通知..環(huán)繞后
注解類(lèi)型后置通知
========================分割線===================================
因?yàn)槭褂昧俗⒔夥绞剑耘渲梦募倭撕芏鄡?nèi)容,只需要一句<context:component-scan base-package="com.cjh.aop2"/>
聲明要掃描的包,框架會(huì)自動(dòng)掃描注釋并生成bean對(duì)象。有個(gè)@Component("knight")
這個(gè)注釋?zhuān)?code><bean id="knight" class="com.cjh.aop2.BraveKnight"/>這個(gè)配置時(shí)一樣的意思,框架會(huì)自動(dòng)識(shí)別并創(chuàng)建名為knight的BraveKnight對(duì)象。所以有了注釋?zhuān)恍枰_(kāi)啟注釋掃描配置就好了,無(wú)需再做相同的bean配置。
如果運(yùn)行過(guò)程中出現(xiàn)Spring aop : error at ::0 can't find referenced pointcut sleepPonit
的錯(cuò)誤,那么很可能是spring的包的版本問(wèn)題,
我用的是spring4的版本,然后還需要加aspectjrt-1.7.4.jar和aspectjweaver-1.7.4.jar兩個(gè)包
下載地址:aspectjrt_aspectjweaver.rar
工程目錄如下:(打碼碼的類(lèi)不用管,只是為了不為大家造成誤導(dǎo),所以劃掉了)
通知注解類(lèi)型如下:
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持
原文鏈接:http://www.cnblogs.com/caijh/p/7154691.html