Spring 中aop切面注解實現


spring中aop的注解實現方式簡單實例

 

  上篇中我們講到spring的xml實現,這里我們講講使用注解如何實現aop呢。前面已經講過aop的簡單理解了,這里就不在贅述了。

注解方式實現aop我們主要分為如下幾個步驟(自己整理的,有更好的方法的話,歡迎交流codecjh@163.com):

  1.在切面類(為切點服務的類)前用@Aspect注釋修飾,聲明為一個切面類。

  2.用@Pointcut注釋聲明一個切點,目的是為了告訴切面,誰是它的服務對象。(此注釋修飾的方法的方法體為空,不需要寫功能比如 public void say(){};就可以了,方法名可以被候命的具體服務功能所以引用,它可以被理解為切點對象的一個代理對象方法)

  3.在對應的方法前用對應的通知類型注釋修飾,將對應的方法聲明稱一個切面功能,為了切點而服務

  4.在spring配置文件中開啟aop注釋自動代理。如:<aop:aspectj-autoproxy/>

這樣講可能還是很抽象,那么,廢話不多說,我們代碼說話,代碼如下:

騎士類:(看過上一篇內容的就知道騎士是什么東西了,嘿嘿嘿)

復制代碼
 1 package com.cjh.aop2;
 2 
 3 import org.springframework.stereotype.Component;
 4 
 5 /**
 6  * @author 古斌
 7  *
 9  */
10 @Component("knight")
11 public class BraveKnight {
12     public void saying(){
13         System.out.println("我是騎士..(切點方法)");
14     }
15 }
復制代碼

切面類:(注釋主要在這里體現)

復制代碼
 1 package com.cjh.aop2;
 2 
 3 import org.aspectj.lang.ProceedingJoinPoint;
 4 import org.aspectj.lang.annotation.After;
 5 import org.aspectj.lang.annotation.Around;
 6 import org.aspectj.lang.annotation.Aspect;
 7 import org.aspectj.lang.annotation.Before;
 8 import org.aspectj.lang.annotation.Pointcut;
 9 import org.springframework.stereotype.Component;
10 
11 /**
15  */

@AspectJ提供不同的通知類型

····@Before前置通知,相當於BeforeAdvice

····@AfterReturning后置通知,相當於AfterReturningAdvice

····@Around環繞通知,相當於MethodInterceptor

····@AfterThrowing拋出通知,相當於ThrowAdvice

····@After最終final通知,不管是否異常,該通知都會執行

 

16 /**
17  * 注解方式聲明aop
18  * 1.用@Aspect注解將類聲明為切面(如果用@Component("")注解注釋為一個bean對象,那么就要在spring配置文件中開啟注解掃描,<context:component-scan base-package="com.cjh.aop2"/>
19  *      否則要在spring配置文件中聲明一個bean對象)
20  * 2.在切面需要實現相應方法的前面加上相應的注釋,也就是通知類型。
21  * 3.此處有環繞通知,環繞通知方法一定要有ProceedingJoinPoint類型的參數傳入,然后執行對應的proceed()方法,環繞才能實現。
22  */
23 @Component("annotationTest")
24 @Aspect
25 public class AnnotationTest {
26     //定義切點
27     @Pointcut("execution(* *.saying(..))")
28     public void sayings(){}
29     /**
30      * 前置通知(注解中的sayings()方法,其實就是上面定義pointcut切點注解所修飾的方法名,那只是個代理對象,不需要寫具體方法,
31      * 相當於xml聲明切面的id名,如下,相當於id="embark",用於供其他通知類型引用)
32      * <aop:config>
33         <aop:aspect ref="mistrel">
34             <!-- 定義切點 -->
35             <aop:pointcut expression="execution(* *.saying(..))" id="embark"/>
36             <!-- 聲明前置通知 (在切點方法被執行前調用) -->
37             <aop:before method="beforSay" pointcut-ref="embark"/>
38             <!-- 聲明后置通知 (在切點方法被執行后調用) -->
39             <aop:after method="afterSay" pointcut-ref="embark"/>
40         </aop:aspect>
41        </aop:config>
42      */
43     @Before("sayings()")
44     public void sayHello(){
45         System.out.println("注解類型前置通知");
46     }
47     //后置通知
48     @After("sayings()")
49     public void sayGoodbey(){
50         System.out.println("注解類型后置通知");
51     }
52     //環繞通知。注意要有ProceedingJoinPoint參數傳入。
53     @Around("sayings()")
54     public void sayAround(ProceedingJoinPoint pjp) throws Throwable{
55         System.out.println("注解類型環繞通知..環繞前");
56         pjp.proceed();//執行方法
57         System.out.println("注解類型環繞通知..環繞后");
58     }
59 }
復制代碼

spring配置文件:

復制代碼
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:context="http://www.springframework.org/schema/context"
 5     xmlns:aop="http://www.springframework.org/schema/aop"
 6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 7         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
 8         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 9     <!-- 開啟注解掃描 -->
10     <context:component-scan base-package="com.cjh.aop2"/>
11     <!-- 開啟aop注解方式,此步驟s不能少,這樣java類中的aop注解才會生效 -->
12     <aop:aspectj-autoproxy/>
13 </beans>
復制代碼

測試代碼:

復制代碼
 1 package com.cjh.aop2;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 /**
 7  * 
11  */
12 public class Test {
13     public static void main(String[] args) {
14         ApplicationContext ac = new ClassPathXmlApplicationContext("com/cjh/aop2/beans.xml");
15         BraveKnight br = (BraveKnight) ac.getBean("knight");
16         br.saying();
17     }
18 }
復制代碼

運行結果:

注解類型環繞通知..環繞前
注解類型前置通知
我是騎士..(切點方法)
注解類型環繞通知..環繞后
注解類型后置通知

========================分割線===================================

  因為使用了注解方式,所以配置文件少了很多內容,只需要一句<context:component-scan base-package="com.cjh.aop2"/>聲明要掃描的包,框架會自動掃描注釋並生成bean對象。有個@Component("knight")這個注釋,和<bean id="knight" class="com.cjh.aop2.BraveKnight"/>這個配置時一樣的意思,框架會自動識別並創建名為knight的BraveKnight對象。所以有了注釋,只需要開啟注釋掃描配置就好了,無需再做相同的bean配置。

  如果運行過程中出現Spring aop : error at ::0 can't find referenced pointcut sleepPonit的錯誤,那么很可能是spring的包的版本問題,

  我用的是spring4的版本,然后還需要加aspectjrt-1.7.4.jar和aspectjweaver-1.7.4.jar兩個包,雲盤地址:鏈接:http://pan.baidu.com/s/1qXQurO4 密碼:nc4i

工程目錄如下:(打碼碼的類不用管,只是為了不為大家造成誤導,所以划掉了)

通知注解類型如下:

 

上圖:

XML的配置:

 

 切入點:

切面:

 

 測試

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM