介绍spring AOP前置通知、后置通知、返回通知、异常通知、环绕通知
依赖:
1.aspectjrt
2.aspectjweaver
详细:
pom.xml 增加配置:
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.9</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> <scope>runtime</scope> </dependency> </dependencies>
ArithmeticCalculator.java
package com.shuoeasy.test; /** * 定义计算器接口 * */ public interface ArithmeticCalculator { double add(double num1, double num2); double sub(double num1, double num2); double mul(double num1, double num2); double div(int num1, int num2); }
ArithmeticCalculatorImpl.java:
package com.shuoeasy.test; import org.springframework.stereotype.Component; /** * 业务类 */ @Component("arithmeticCalculator") public class ArithmeticCalculatorImpl implements ArithmeticCalculator{ public double add(double num1, double num2) { double result = num1 + num2; return result; } public double sub(double num1, double num2) { double result = num1 - num2; return result; } public double mul(double num1, double num2) { double result = num1 * num2; return result; } public double div(int num1, int num2) { double result = num1 / num2; return result; } }
LogAspect.java
package com.shuoeasy.test; import java.util.Arrays; 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.springframework.stereotype.Component; // 声明为一个切面:需要把该类放入IOC容器中、再声明为一个切面 @Aspect @Component public class LogAspect { public static final String EDP = "execution(public double com.shuoeasy.test.ArithmeticCalculator.add(double, double))"; // 前置通知。声明该方法是一个前置通知:在目标方法之前执行 @Before(EDP) public void beforeMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("The method " + methodName + " @Before, args:" + Arrays.asList(args)); } // 后置通知。目标方法执行之后执行,无论该方法是否出现异常 @After("execution(* com.shuoeasy.test.*.*(..))") public void afterMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("The method " + methodName + " @After, args:" + Arrays.asList(args)); } // 返回通知。在方法正常执行后,返回通知是可以访问该方法返回值的 @AfterReturning(value="execution(* com.shuoeasy.test.*.*(..))",returning="result") public void afterReturning(JoinPoint joinPoint, Object result){ String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("The method " + methodName + " @AfterReturning, return:" + result); } // 异常通知。在目标方法出现异常时执行代码,可以访问到异常对象,且可以指定出现特定异常时执行通知代码 @AfterThrowing(value="execution(* com.shuoeasy.test.*.*(..))",throwing="ex") public void afterThrowing(JoinPoint joinPoint, Exception ex){ // 也可以将Exception改为特定的异常类型NullPointerException ex String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " @AfterThrowing, ex:" + ex.toString()); } // 环绕通知。需要携带ProceedingJoinPoint类型的参数。 // 类似动态代理的全过程ProceedingJoinPoint类型的参数可以决定是否执行目标方法。 // 且环绕通知有返回值,返回值即目标方法的返回值 @Around("execution(* com.shuoeasy.test.*.*(..))") public Object aroundMethod(ProceedingJoinPoint pjd){ //return 100.0; // 如果return 100.0,目标方法的返回值就被强制改为100.0 Object result = null; String methodName = pjd.getSignature().getName(); Object[] args = pjd.getArgs(); try { // 前置通知 System.out.println("The method " + methodName + " @Around->Before, args:" + Arrays.asList(args)); // 执行目标方法 result = pjd.proceed(); // 后置通知 System.out.println("The method " + methodName + " @Around->AfterReturning, return:" + result); } catch (Throwable e) { // 异常通知 System.out.println("The method " + methodName + " @Around->AfterThrowing, e:" + e.toString()); throw new RuntimeException(e); } // 后置通知 System.out.println("The method " + methodName + " @After, args:" + Arrays.asList(args)); return result; } }
bean.xml
<?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:p="http://www.springframework.org/schema/p" 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/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> <!-- 自动扫描的包 --> <context:component-scan base-package="com.shuoeasy.test"></context:component-scan> <!-- 使用Aspjectj 注解起作用:自动为匹配的类生成代理对象 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
Main.java
package com.shuoeasy.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { // 1.创建spring的IOC容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml"); // 2.从IOC容器中获取bean的实例 ArithmeticCalculator arithmeticCalulator = (ArithmeticCalculator)ctx.getBean("arithmeticCalculator"); // 3.使用bean double result = arithmeticCalulator.add(2, 3); System.out.println("result=" + result); } }
输出:
The method add @Around->Before, args:[2.0, 3.0]
The method add @Before, args:[2.0, 3.0]
The method add @Around->AfterReturning, return:5.0
The method add @After, args:[2.0, 3.0]
The method add @After, args:[2.0, 3.0]
The method add @AfterReturning, return:5.0
result=5.0