Spring註解式AOP面向切面編程.

1、AOP指在程序運行期間動態的將某段代碼切入到指定方法指定位置進行運行的編程方式。aop底層是動態代理。

 1 package com.bie.config;
 2 
 3 import org.aspectj.lang.annotation.Aspect;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.context.annotation.EnableAspectJAutoProxy;
 7 
 8 import com.bie.aop.LogAspect;
 9 import com.bie.aop.MathCalculator;
10 
11 /**
12  * 
13  *
14  * @Title: SpringApplicationConfig.java
15  * @Package com.bie.config
16  * @Description: TODO
17  * @author biehl
18  * @date 2019年12月9日
19  * @version V1.0
20  * 
21  * 
22  *          1、AOP指在程序運行期間動態的將某段代碼切入到指定方法指定位置進行運行的編程方式。aop底層是動態代理。
23  * 
24  *          第一步、導入aop模塊,spring-aspects。
25  *          第二步、定義業務邏輯類,MathCalculator。在業務邏輯運行的時候打印日誌(方法運行之前,方法運行結束,方法出現異常打印日誌。)。
26  *          第三步、定義一個日誌切面類LogAspect,切面類裏面的方法需要動態感知到類的方法MathCalculator.div運行到那一步了。然後開始執行。
27  *              通知方法介紹: 
28  *                  前置通知:logStart,在目標方法運行之前運行。註解@Before
29  *                  後置通知:logEnd,在目標方法運行結束之後運行,無論方法正常結束還是異常結束。註解@After
30  *                  返回通知:logReturn,在目標方法運行正常返回之後運行。註解@AfterRetruning
31  *                  異常通知:logException,在目標方法運行異常返回之後運行。註解@AfterThrowing
32  *                  環繞通知:動態代理。手動推進目標方法運行。 註解@Around
33  *          第四步、根據通知方法給切面類的目標方法標註何時何地運行。標註通知註解。
34  *          第五步、將切面類,和業務邏輯層(目標方法所在的類)都加如到容器中。使用@Bean註解或者@Component註解即可。
35  *          第六步、告訴Spring那個類是切面類。給切面類加一個@Aspect註解。
36  *             第七步、開啓基於註解版的aop模式切面功能。啓用該註解@EnableAspectJAutoProxy,啓動AspectJ自動代理。
37  *                 @EnableXXX開啓某項功能。
38  * 
39  *             AOP切面編程重要的三步走:
40  *                 第一步、將業務邏輯組件和切面類都加入到容器中。告訴spring容器那個是切面類(@Aspect)。
41  *                 第二步、在切面類上的每個通知方法上標註通知註解,告訴spring何時何地運行(注意切入點表達式的書寫)。
42  *                 第三步、開啓基於註解版的aop模式切面功能。啓用該註解@EnableAspectJAutoProxy,啓動AspectJ自動代理。
43  */
44 // @Configuration告訴Spring這是一個配置類,相當於bean.xml配置文件。
45 @Configuration
46 @EnableAspectJAutoProxy
47 public class SpringApplicationConfig15 {
48 
49     /**
50      * 將目標類加入到容器中
51      * 
52      * @return
53      */
54     @Bean
55     public MathCalculator mathCalculator() {
56         return new MathCalculator();
57     }
58     
59     
60     /**
61      * 將切面類加入到容器中
62      * 
63      * @return
64      */
65     @Bean
66     public LogAspect logAspect() {
67         return new LogAspect();
68     }
69     
70 }

開發業務邏輯層類,如下所示:

 1 package com.bie.aop;
 2 
 3 /**
 4  * 
 5  *
 6  * @Title: MathCalculator.java
 7  * @Package com.bie.aop
 8  * @Description: TODO
 9  * @author biehl
10  * @date 2019年12月12日
11  * @version V1.0
12  *
13  */
14 public class MathCalculator {
15 
16     /**
17      * 
18      * @param i
19      * @param j
20      * @return
21      */
22     public int div(int i, int j) {
23         System.out.println(i + " / " + j + " = " + i / j);
24         return i / j;
25     }
26 
27 }

開發切面類,如下所示:

  1 package com.bie.aop;
  2 
  3 import java.util.Arrays;
  4 
  5 import org.aspectj.lang.JoinPoint;
  6 import org.aspectj.lang.annotation.After;
  7 import org.aspectj.lang.annotation.AfterReturning;
  8 import org.aspectj.lang.annotation.AfterThrowing;
  9 import org.aspectj.lang.annotation.Aspect;
 10 import org.aspectj.lang.annotation.Before;
 11 import org.aspectj.lang.annotation.Pointcut;
 12 
 13 /**
 14  * 
 15  *
 16  * @Title: LogAspect.java
 17  * @Package com.bie.aop
 18  * @Description: TODO
 19  * @author biehl
 20  * @date 2019年12月12日
 21  * @version V1.0
 22  * 
 23  *          日誌切面類
 24  */
 25 @Aspect // 告訴Spring容器,當前類是切面類
 26 public class LogAspect {
 27 
 28     /**
 29      * 抽取公共的切入點表達式
 30      * 
 31      * 方式一,如果是本類引用,直接使用即可,@Before("pointCut()")
 32      * 方式二,其他的切面類引入,加上類路徑即可@Before("com.bie.aop.LogAspect.pointCut()")
 33      */
 34     @Pointcut(value = "execution(* com.bie.aop.MathCalculator.*(..))")
 35     public void pointCut() {
 36     }
 37 
 38     /**
 39      * JoinPoint參數必須出現在參數的第一位
 40      * 
 41      * 方法運行前執行該方法。@Before目標方法之前切入。
 42      * 
 43      * 切入點表達式,public int com.bie.aop.MathCalculator.div(int int)。 指定在那個方法切入。
 44      * 
 45      * Signature簽名是方法的簽名。
 46      */
 47     @Before(value = "pointCut()")
 48     public void logStart(JoinPoint joinPoint) {
 49         // 獲取到方法參數列表
 50         Object[] args = joinPoint.getArgs();
 51         // 獲取到方法名稱
 52         String methodName = joinPoint.getSignature().getName();
 53         System.out.println(methodName + "()方法名稱, @Before除法方法執行了......參數列表是{" + Arrays.asList(args) + "}");
 54     }
 55 
 56     /**
 57      * JoinPoint參數必須出現在參數的第一位
 58      * 
 59      * 方法運行後執行該方法
 60      * 
 61      * @After(value = "public int com.bie.aop.MathCalculator.*(..)")
 62      *              代表了MathCalculator該類的所有方法。所有方法的任意參數。
 63      * 
 64      */
 65     @After(value = "pointCut()")
 66     public void logEnd(JoinPoint joinPoint) {
 67         // 獲取到方法參數列表
 68         Object[] args = joinPoint.getArgs();
 69         // 獲取到方法名稱
 70         String methodName = joinPoint.getSignature().getName();
 71         System.out.println(methodName + "()方法名稱, @After除法方法結束了......參數列表是{" + Arrays.asList(args) + "}");
 72     }
 73 
 74     /**
 75      * JoinPoint參數必須出現在參數的第一位
 76      * 
 77      * returning指定誰來封裝返回值。
 78      * 
 79      * @param result
 80      *            參數封裝返回值
 81      */
 82     @AfterReturning(value = "pointCut()", returning = "result")
 83     public void logReturn(JoinPoint joinPoint, Object result) {
 84         // 獲取到方法名稱
 85         String methodName = joinPoint.getSignature().getName();
 86         System.out.println(methodName + "()方法名稱, @AfterReturning除法方法正常返回了......運行結果是{" + result + "}");
 87     }
 88 
 89     /**
 90      * JoinPoint參數必須出現在參數的第一位
 91      * 
 92      * throwing指定誰來封裝返回值。
 93      * 
 94      * @param exception
 95      *            參數封裝返回值
 96      */
 97     @AfterThrowing(value = "pointCut()", throwing = "exception")
 98     public void logException(JoinPoint joinPoint, Exception exception) {
 99         // 獲取到方法名稱
100         String methodName = joinPoint.getSignature().getName();
101         System.out.println(methodName + "()方法名稱, @AfterThrowing除法方法異常了......異常信息是{" + exception + "}");
102     }
103 
104 }

測試主類,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.beans.BeansException;
 4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 5 
 6 import com.bie.aop.MathCalculator;
 7 import com.bie.config.SpringApplicationConfig15;
 8 
 9 /**
10  * 
11  *
12  * @Title: SpringApplication.java
13  * @Package com.bie.main
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  *
19  */
20 public class SpringApplication {
21 
22     public static void main(String[] args) {
23         // 獲取到註解配置類
24         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig15.class);
25 
26         try {
27             // 使用容器中獲取到目標對象,而不是自己創建對象。
28             MathCalculator mathCalculator = ac.getBean(MathCalculator.class);
29             mathCalculator.div(42, 2);
30         } catch (BeansException e) {
31             e.printStackTrace();
32         }
33 
34         // 調用關閉的時候,調用destory銷燬方法。
35         ac.close();
36     }
37 
38 }

 

作者:別先生

博客園:https://www.cnblogs.com/biehongli/

如果您想及時得到個人撰寫文章以及著作的消息推送,可以掃描上方二維碼,關注個人公衆號哦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章