實現兩個整數的加減乘除、在執行每個方法之前打印日志。
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)
