1. 程式人生 > >前置通知

前置通知

初始 配置文件 返回 方法 生成 void around color 文件中

【Spring AOP】

1.AspectJ:Java社區裏最完整最流行的AOP框架。

2.在Spring2.0 以上的版本中,可以使用基於AspectJ註解或基於XML配置的AOP。

【在Spring中啟用AspectJ註解支持】

1.要在Spring應用中使用AspectJ註解,必須在classpath下包含AspectJ類庫:aopalliance.jar、aspectj.weaver.jar和spring-aspects.jar。

2.將aop Schema添加到<beans>根元素中

3.要在Spring IOC容器中啟用AspectJ註解支持,只要在Bean配置文件中定義一個空的XML元素<aop:aspectj-autoproxy>。

4.當Spring IOC容器偵測到Bean配置文件中的<aop:aspectj-autoproxy>元素時,會自動為與AspectJ切面匹配的Bean創建代理。

【用AspectJ註解聲明切面】

1.要在Spring中聲明AspectJ切面,只需要在IOC容器中將切面聲明為Bean實例。當在Spring IOC容器中初始化AspectJ切面之後,Spring IOC 容器就會為那些與AspectJ切面相匹配的Bean創建代理。

2.在AspectJ註解中,切面只是一個帶有@Aspect註解的Java類

3.通知是標註有某種註解的簡單的Java方法

4.AspectJ支持5種類型的通知註解:

--@Before:前置通知,在方法執行之前執行

--@After:後置通知,在方法執行之後執行

--@AfterRunning:返回通知,在方法返回結果之後執行

--@AfterThrowing:異常通知,在方法拋出異常之後

--@Around:環繞通知,圍繞著方法執行

實現:在result結果輸出前會有一個提示語句輸出。

LoggingAspect.java:

 1 package com.hk.spring.aop.impl;
 2 
 3 import java.util.Arrays;
 4 import java.util.List;
 5 import org.aspectj.lang.JoinPoint;
6 import org.aspectj.lang.annotation.Aspect; 7 import org.aspectj.lang.annotation.Before; 8 import org.springframework.stereotype.Component; 9 10 //把這個類聲明為一個切面。步驟:需要把該類放入到IOC容器中,然後再聲明為一個切面。 11 @Aspect 12 @Component 13 public class LoggingAspect { 14 //聲明該方法是一個前置通知:在目標方法之前執行 15 @Before("execution(public int com.hk.spring.aop.impl.ArithmeticCalculator.add(int,int))") 16 public void beforeMethod(JoinPoint joinPoint){ 17 String methodName = joinPoint.getSignature().getName(); 18 List<Object> args = Arrays.asList(joinPoint.getArgs()); 19 System.out.println("The method " + methodName + " begins with " + args); 20 } 21 }

applicationContext.xml:

 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:aop="http://www.springframework.org/schema/aop"
 5     xmlns:context="http://www.springframework.org/schema/context"
 6     xsi:schemaLocation="http://www.springframework.org/schema/beans 
 7         http://www.springframework.org/schema/beans/spring-beans.xsd
 8         http://www.springframework.org/schema/context 
 9         http://www.springframework.org/schema/context/spring-context-4.3.xsd
10         http://www.springframework.org/schema/aop 
11         http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
12 
13   <!-- 配置自動掃描的包 -->
14   <context:component-scan base-package="com.hk.spring.aop.impl"></context:component-scan>
15   
16   <!-- 使AspectJ 註解起作用:自動為匹配的類生成代理對象 -->
17   <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
18 </beans>

Main.java:

 1 package com.hk.spring.aop.impl;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class Main {
 7     public static void main(String[] args) {
 8         //1.創建Spring的IOC容器
 9         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
10         
11         //2.從IOC容器中獲取Bean的實例
12         ArithmeticCalculator arithmeticCalculator = ctx.getBean(ArithmeticCalculator.class);
13         //3.使用bean
14         int result = arithmeticCalculator.add(3, 6);
15         System.out.println("result:" + result);
16     }
17 
18 }

運行結果:

技術分享圖片

假如在Main.java代碼最後再加入:

1         result = arithmeticCalculator.div(12, 6);
2         System.out.println("result:" + result);

要使切面代碼對該句也有效,需要在切面代碼中把add改為*,否則不會有效,下圖示:

技術分享圖片

註:如果不改動代碼仍為add,那就是表明只對add方法有效。

【利用方法簽名編寫AspectJ切入點表達式】

1.最典型的切入點表達式是根據方法的簽名來匹配各種方法

--execution * com.hk.spring.aop.impl.ArithmeticCalculator.*(..):匹配ArithmeticCalculator中聲明的所有方法,第一個 “ * ” 代表任意修飾符以及任意返回值,第二個“ * ” 代表任意方法。“ .. ”匹配任意數量的參數。若目標類與接口與該切面在同一個包中,可以省略包名。

--execution public* ArithmeticCalculator.*(..):匹配ArithmeticCalculator接口的所有公有方法。

--execution public double ArithmeticCalculator.*(..):匹配ArithmeticCalculator中返回double類型數值的方法。

--execution public double ArithmeticCalculator.*(double,..):匹配第一個參數為double類型的方法,“ .. ” 匹配任意數量任意類型的參數。

--execution public double ArithmeticCalculator.*(double,double):匹配參數類型為 double,double 類型的方法。

運行結果:

技術分享圖片

【讓通知訪問當前連接點的細節】

可以在通知方法中聲明一個類型為JoinPoint的參數。然後就能訪問鏈接細節。如方法名稱和參數值。

附:

技術分享圖片

小結:

1.Spring AOP

(1)加入jar包:

技術分享圖片

(2)在配置文件中加入AOP命名空間。

(3)基於註解的方式

①在配置文件中加入如下配置:

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

②把橫切關註點的代碼抽象到切面的類中。

(i)切面首先是一個IOC中的Bean,即加入 @Component 註解

(ii)切面還需要@Aspect 註解

③在類中聲明各種通知:

(i)聲明一個方法

(ii)在一個方法前加入@Before註解

④可以在通知方法中聲明一個類型為JoinPoint的參數。然後就能訪問鏈接細節。如方法名稱和參數值。

 1 //把這個類聲明為一個切面。步驟:需要把該類放入到IOC容器中,然後再聲明為一個切面。
 2 @Aspect
 3 @Component
 4 public class LoggingAspect {
 5     //聲明該方法是一個前置通知:在目標方法之前執行
 6     @Before("execution(public int com.hk.spring.aop.impl.ArithmeticCalculator.*(int,int))")
 7     public void beforeMethod(JoinPoint joinPoint){
 8         String methodName = joinPoint.getSignature().getName();
 9         List<Object> args = Arrays.asList(joinPoint.getArgs());
10         System.out.println("The method " + methodName + " begins with " + args);
11     }

前置通知