Spring初学之annotation实现AOP前置通知后置通知返回通知异常通知。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring初学之annotation实现AOP前置通知后置通知返回通知异常通知。相关的知识,希望对你有一定的参考价值。
实现两个整数的加减乘除、在执行每个方法之前打印日志。
ArithmeticCalculator.java:
package spring.aop.impl; public interface ArithmeticCalculator { int add(int i,int j); int sub(int i,int j); int mul(int i,int j); int div(int i,int j); }
ArithmeticCalculatorImpl.java:
package spring.aop.impl; import org.springframework.stereotype.Component; @Component("arithmeticCalculator") public class ArithmeticCalculatorImpl implements ArithmeticCalculator { public int add(int i, int j) { int result = i+j; return result; } public int sub(int i, int j) { int result = i-j; return result; } public int mul(int i, int j) { int result = i*j; return result; } public int div(int i, int j) { int result = i/j; return result; } }
LoggingAspect.java:
package spring.aop.impl; import java.util.Arrays; import java.util.List; 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.core.annotation.Order; import org.springframework.stereotype.Component; @Order(1)//如果有多个切面,可以使用@Order来指定切面的优先级,值越小优先级越高 @Aspect @Component public class LoggingAspect { /** * 定义一个方法,定义切入点表达式,一般地,这个方法中不添加其它代码 * 怎么使用? * 1.如果在本类,如@Before("declareJoinPointExpression()"),直接用方法名来引用 * 2.在另一个包的类或其他类,如@Before("包名.类名.declareJoinPointExpression()") */ @Pointcut("execution(public int spring.aop.impl.ArithmeticCalculator.*(..))") public void declareJoinPointExpression(){} /** * 在spring.aop.impl.ArithmeticCalculator接口的每一个实现类的每一个开始之前执行一段代码 */ @Before("declareJoinPointExpression()") public void beforeMethod(JoinPoint joinPoint){ String methodName=joinPoint.getSignature().getName(); List<Object> args=Arrays.asList(joinPoint.getArgs()); System.out.println("The method "+methodName+" begins "+args); } /** * 在方法之后执行(不论是否抛出异常) * @param joinPoint */ @After("execution(public int spring.aop.impl.ArithmeticCalculator.*(..))") public void afterMethod(JoinPoint joinPoint){ String methodName=joinPoint.getSignature().getName(); List<Object> args=Arrays.asList(joinPoint.getArgs()); System.out.println("The method "+methodName+" ends "); } /** * 在方法正常执行后的通知 * 返回通知是可以访问到方法的返回值的 * @param joinPoint */ @AfterReturning(value="execution(public int spring.aop.impl.ArithmeticCalculator.*(..))", returning="result") public void afterReturnMethod(JoinPoint joinPoint,Object result){ String methodName=joinPoint.getSignature().getName(); System.out.println("The method "+methodName+" ends with afterReturning "+ result); } /** * 在目标方法出现异常时会执行的代码 * 可以访问出现的异常信息,可以指定出现指定异常时执行 * 方法参数Exception改为其它异常可以指定出现指定异常时执行 * @param joinPoint * @param ex */ @AfterThrowing(value="execution(public int spring.aop.impl.ArithmeticCalculator.*(..))", throwing="ex") public void afterThrowing(JoinPoint joinPoint,Exception ex){ String methodName=joinPoint.getSignature().getName(); System.out.println("The method "+methodName+" occurs exection: "+ ex); } /** * 环绕通知 * 需要携带ProceedingJoinPoint类型的参数 * 类似于动态代理的全过程:ProceedingJoinPoint类型参数可以决定是否执行目标方法 * 环绕通知必须有返回值,返回值就是目标方法的返回值 * @param joinPoint */ /* @Around("execution(public int spring.aop.impl.ArithmeticCalculator.*(..))") public Object aroundMethod(ProceedingJoinPoint joinPoint){ Object result=null; String methodName=joinPoint.getSignature().getName(); try { //前置通知 System.out.println("---->The method "+methodName+" begins with" +Arrays.asList(joinPoint.getArgs())); //执行目标方法 result=joinPoint.proceed(); //返回通知 System.out.println("---->"+result); } catch (Throwable e) { e.printStackTrace(); //异常通知 System.out.println("---->"+e); } //后置通知 System.out.println("---->The method "+methodName+ "ends"); return result; } */ }
ApplicationContext.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 配置自动扫描的包 --> <context:component-scan base-package="spring.aop.impl"></context:component-scan> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
测试:
package spring.aop.impl.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import spring.aop.impl.ArithmeticCalculator; public class Main { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); ArithmeticCalculator arithmeticCalculator=(ArithmeticCalculator) ctx.getBean("arithmeticCalculator"); int result=arithmeticCalculator.add(10, 20); System.out.println("result:"+result); result=arithmeticCalculator.div(10, 0); System.out.println("result:"+result); } }
输出:
The method add begins [10, 20] The method add ends The method add ends with afterReturning 30 result:30 The method div begins [10, 0] The method div ends The method div occurs exection: java.lang.ArithmeticException: / by zero Exception in thread "main" java.lang.ArithmeticException: / by zero at spring.aop.impl.ArithmeticCalculatorImpl.div(ArithmeticCalculatorImpl.java:24) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) at com.sun.proxy.$Proxy12.div(Unknown Source) at spring.aop.impl.test.Main.main(Main.java:18)
以上是关于Spring初学之annotation实现AOP前置通知后置通知返回通知异常通知。的主要内容,如果未能解决你的问题,请参考以下文章
Spring初学之xml实现AOP前置通知后置通知返回通知异常通知等
Spring-AOP @AspectJ切点函数之@annotation()
基于 Annotation 的 Spring AOP 权限验证方法的实现
Spring Cloud项目如何防止重复提交,防重复提交幂等校验,Redis+aop+自定义Annotation实现接口