基于XML 配置文件的 Spring AOP 前置通知 后置通知 异常通知 返回通知 以及环绕通知
接口:ArithmeticCalculator.jav
package spring.aop.xml; public interface ArithmeticCalculator { public int add(int i, int j); public int sub(int i, int j); public int mul(int i, int j); public int div(int i, int j); }
接口实现类: ArithmeticCalculatorImpl.java
package spring.aop.xml; import org.springframework.stereotype.Component; @Component public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override public int add(int i, int j) { int result = i + j; return result; } @Override public int sub(int i, int j) { int result = i - j; return result; } @Override public int mul(int i, int j) { int result = i * j; return result; } @Override public int div(int i, int j) { int result = i/j; return result; } }
打Log的切面函数: LoggingAspect.java
package spring.aop.xml; import java.util.Arrays; import java.util.List; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.stereotype.Component; //把这个类声明为一个切面:需要把该类放入到IOC容器中, 声明为一个切面 @Component public class LoggingAspect { public void declareJoinPointExpression() { } public void beforeMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The " + methodName + " begins " + " args is: " + args); } public void afterMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The " + methodName + " ends " + methodName + " args is: " + args); } public void afterReturning(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); System.out.println("The " + methodName + " ends " + methodName + " return is: " + result); } public void afterThrowing(JoinPoint joinPoint, Exception ex) { String methodName = joinPoint.getSignature().getName(); System.out.println("The " + methodName + " occurs exception " + ex); } /** * 环绕通知需要携带ProceedingJoinPoint类型的参数 环绕通知类似于动态代理的全过程: ProceedingJoinPoint * 类型的参数可以决定是否执行目标方法 且环绕通知必须有返回值,返回值即为目标方法的返回值 * * @param pjd */ public Object aroundMethod(ProceedingJoinPoint pjd) { Object result = null; String methodName = pjd.getSignature().getName(); try { // 前置通知 System.out .println("@Around before ----> The " + methodName + " begin with " + Arrays.asList(pjd.getArgs())); result = pjd.proceed(); // 返回通知 System.out.println("@Around return ----> The " + methodName + " return with " + result); } catch (Throwable e) { System.out.println("@Around exception ----> The " + methodName + " occurs exception " + e); throw new RuntimeException(e); } // 后置通知 System.out.println("@Around after ----> The " + methodName + " ends"); return result; } }
验证结果的切面函数: ValidateResult.java
package spring.aop.xml; import java.util.Arrays; import java.util.List; import org.aspectj.lang.JoinPoint; import org.springframework.stereotype.Component; @Component public class ValidateResult { public void validateResult(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("Validate " + methodName + args); } }
Main.java
package spring.aop.xml; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args){ int result; ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-xml.xml"); ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator)ctx.getBean(ArithmeticCalculator.class); result = arithmeticCalculator.add(1, 2); System.out.println(result); result = arithmeticCalculator.div(4, 1); System.out.println(result); } }
配置文件:
applicationContext-xml.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: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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <bean id="arithmeticCalculatorImpl" class="spring.aop.xml.ArithmeticCalculatorImpl"></bean> <bean id="loggingAspect" class="spring.aop.xml.LoggingAspect"></bean> <bean id="validateResult" class="spring.aop.xml.ValidateResult"></bean> <!-- 配置AOP --> <aop:config> <!-- 配置切点表达式 --> <aop:pointcut expression="execution(* spring.aop.xml.ArithmeticCalculator.* (int, int))" id="pointcut"/> <!-- 配置切面通知 --> <aop:aspect ref="loggingAspect" order="2"> <aop:before method="beforeMethod" pointcut-ref="pointcut"/> <aop:after method="afterMethod" pointcut-ref="pointcut"/> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/> <aop:around method="aroundMethod" pointcut-ref="pointcut" /> </aop:aspect> <aop:aspect ref="validateResult" order="1"> <aop:before method="validateResult" pointcut-ref="pointcut"/> </aop:aspect> </aop:config> </beans>