Spring AOP面向切面編程,能夠用來配置事務、作日誌、權限驗證、在用戶請求時作一些處理等等。用@Aspect作一個切面,就能夠直接實現。java
· 本例演示一個基於@Aspect的小demospring
一、新建一個Maven工程express
二、引入相關maven依賴apache
1 <project xmlns="http://maven.apache.org/POM/4.0.0" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <groupId>com.test</groupId> 6 <artifactId>test-spring-aop</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 9 <!-- 定義maven變量 --> 10 <properties> 11 <!-- spring --> 12 <spring.version>5.1.4.RELEASE</spring.version> 13 </properties> 14 15 <dependencies> 16 <!-- Spring IOC 核心容器 --> 17 <dependency> 18 <groupId>org.springframework</groupId> 19 <artifactId>spring-core</artifactId> 20 <version>${spring.version}</version> 21 </dependency> 22 23 <dependency> 24 <groupId>org.springframework</groupId> 25 <artifactId>spring-beans</artifactId> 26 <version>${spring.version}</version> 27 </dependency> 28 29 <dependency> 30 <groupId>org.springframework</groupId> 31 <artifactId>spring-context</artifactId> 32 <version>${spring.version}</version> 33 </dependency> 34 35 <dependency> 36 <groupId>org.springframework</groupId> 37 <artifactId>spring-expression</artifactId> 38 <version>${spring.version}</version> 39 </dependency> 40 41 <!-- Spring AOP 切面 模塊 --> 42 <dependency> 43 <groupId>org.springframework</groupId> 44 <artifactId>spring-aop</artifactId> 45 <version>${spring.version}</version> 46 </dependency> 47 48 <dependency> 49 <groupId>org.aspectj</groupId> 50 <artifactId>aspectjrt</artifactId> 51 <version>1.9.2</version> 52 </dependency> 53 54 <dependency> 55 <groupId>org.aspectj</groupId> 56 <artifactId>aspectjweaver</artifactId> 57 <version>1.9.2</version> 58 </dependency> 59 60 </dependencies> 61 </project>
三、新建一個SimpleAspect.java類,以下:編程
package com.test.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.Pointcut; import org.springframework.stereotype.Component; /** * @Auther: chenheng * @Date: 2019/7/10 11:56 * @Description: */ @Aspect @Component public class SimpleAspect { /** * 切點表達式: * ..兩個點代表多個,*表明一個 * 表達式表明切入com..service包下的全部類的全部方法,方法參數不限,返回類型不限。 * 其中訪問修飾符能夠不寫,不能用*,,第一個*表明返回類型不限,第二個*表示全部類,第三個*表示全部方法,..兩個點表示方法裏的參數不限。 */ private final String POINT_CUT = "execution(* com..service.*.*(..))"; /** * 命名切點 * public 切點可訪問性修飾符 * 與類可訪問性修飾符的功能是相同的,它能夠決定定義的切點能夠在哪些類中可以使用。 * pointCut 切點名稱 * void 返回類型 * * 由於命名切點僅利用方法名及訪問修飾符的信息, * 通常定義方法的返回類型爲 void ,而且方法體爲空 */ @Pointcut(POINT_CUT) public void pointCut(){} /** * 在切點方法以前執行 * @param joinPoint */ @Before(value="pointCut()") public void doBefore(JoinPoint joinPoint){ System.out.println("@Before:切點方法以前執行....."); } /** * 在切點方法以後執行 * @param joinPoint */ @After(value="pointCut()") public void doAfter(JoinPoint joinPoint){ System.out.println("@After:切點方法以後執行....."); } /** * 切點方法返回後執行 * 若是第一個參數爲JoinPoint,則第二個參數爲返回值的信息 * 若是第一個參數不爲JoinPoint,則第一個參數爲returning中對應的參數 * returning:限定了只有目標方法返回值與通知方法參數類型匹配時才能執行後置返回通知,不然不執行, * 參數爲Object類型將匹配任何目標返回值 */ @AfterReturning(value = "pointCut()",returning = "result") public void doAfter(JoinPoint joinPoint,Object result){ System.out.println("@AfterReturning:切點方法返回後執行....."); System.out.println("返回值:"+result); } /** * 切點方法拋異常執行 * 定義一個名字,該名字用於匹配通知實現方法的一個參數名,當目標方法拋出異常返回後,將把目標方法拋出的異常傳給通知方法; * throwing:限定了只有目標方法拋出的異常與通知方法相應參數異常類型時才能執行後置異常通知,不然不執行, * 對於throwing對應的通知方法參數爲Throwable類型將匹配任何異常。 * @param joinPoint * @param exception */ @AfterThrowing(value = "pointCut()",throwing = "exception") public void doAfterThrowing(JoinPoint joinPoint,Throwable exception){ System.out.println("@afterThrowing:切點方法拋異常執行....."); } /** * * 屬於環繞加強,能控制切點執行前,執行後,,用這個註解後,程序拋異常,會影響@AfterThrowing這個註解 * * org.aspectj.lang.JoinPoint 接口表示目標類鏈接點對象,它定義這些主要方法。 * Object[] getArgs():獲取鏈接點方法運行時的入參列表。 * Signature getSignature():獲取鏈接點的方法簽名對象。 * Object getTarget():獲取鏈接點所在的目標對象。 * Object getThis():獲取代理對象。 * @param pjp * @return * @throws Throwable */ @Around(value="pointCut()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("@Around:切點方法環繞start....."); Object[] args = pjp.getArgs(); Object o = pjp.proceed(args); System.out.println("@Around:切點方法環繞end....."); return o; } }
四、新建一個AspectService.java類,以下:mybatis
1 package com.test.service; 2 3 import org.springframework.stereotype.Service; 4 5 @Service 6 public class AspectService { 7 8 public String sayHi(String name) 9 { 10 System.out.println("方法:sayHi 執行中 ...."); 11 return"Hello, " + name; 12 } 13 14 public void excuteException() 15 { 16 System.out.println("方法:excuteException 執行中 ...."); 17 int n = 1; 18 if(n > 0) { 19 throw new RuntimeException("數據異常"); 20 } 21 } 22 23 24 }
五、新建一個spring配置文件applicationContext.xml,以下:app
<?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" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <!-- 配置自動掃描包 --> <context:component-scan base-package="com.test"></context:component-scan> <!-- 配置開啓@Aspect支持 --> <aop:aspectj-autoproxy proxy-target-class="true" /> </beans>
六、新建一個測試類,以下:maven
1 package com.test.main; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 import com.test.service.AspectService; 7 8 public class TestMain { 9 10 public static void main(String[] args) { 11 12 // ClassPathXmlApplicationContext默認是加載src目錄下的xml文件 13 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 14 15 AspectService aservice = context.getBean(AspectService.class); 16 System.out.println("\n===========普通調用=============\n"); 17 18 aservice.sayHi("hd"); 19 20 System.out.println("\n===========異常調用=============\n"); 21 22 aservice.excuteException(); 23 24 System.out.println("\n========================\n"); 25 } 26 27 }
七、運行測試類,結果以下:ide