基于配置文件的方式来配置 AOP
前边三个章节《Spring(十七):Spring AOP(一):简介》、《Spring(十八):Spring AOP(二):通知(前置、后置、返回、异常、环绕)》、《Spring(十九):Spring AOP(三):切面的优先级、重复使用切入点表达式》讲解AOP时,都采用的是注解方式,如何使用配置文件的方式配置AOP呢?那么,本章节就会使用前边章节的例子,基于文件配置的方式实现AOP配置。
第一步:新建好Spring AOP项目、导入依赖的jar包:
第二步:添加Bean类,和切面类:
IArithmeticCalculator.java接口类
package com.dx.spring.beans.xml; /** * Description:Addition, subtraction, multiplication, and division */ public interface IArithmeticCalculator { int add(int i, int j); int sub(int i, int j); int multi(int i, int j); int div(int i, int j); }
ArithmeticCalculatorImpl.java组件
package com.dx.spring.beans.xml; public class ArithmeticCalculatorImpl implements IArithmeticCalculator { @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 multi(int i, int j) { int result = i * j; return result; } @Override public int div(int i, int j) { int result = i / j; return result; } }
LoggingAspect.java日志切面类:
package com.dx.spring.beans.xml; import java.util.Arrays; import java.util.List; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class LoggingAspect { // 声明该方法为一个前置通知:在目标方法开始之前执行 public void beforeMethod(JoinPoint joinpoint) { String methodName = joinpoint.getSignature().getName(); List<Object> args = Arrays.asList(joinpoint.getArgs()); System.out.println("before method " + methodName + " with " + args); } // 声明该方法为一个后置通知:在目标方法结束之后执行(无论方法是否抛出异常)。 // 但是因为当方法抛出异常时,不能返回值为null,因此这里无法获取到异常值。 public void afterMethod(JoinPoint joinpoint) { String methodName = joinpoint.getSignature().getName(); List<Object> args = Arrays.asList(joinpoint.getArgs()); System.out.println("after method " + methodName); } /** * 声明该方法为一个返回通知:在目标方法返回结果时后执行(当方法抛出异常时,无法执行) */ public void afterReturningMethod(JoinPoint joinpoint, Object result) { String methodName = joinpoint.getSignature().getName(); List<Object> args = Arrays.asList(joinpoint.getArgs()); System.out.println( "after method " + methodName + " with returning " + (result == null ? "NULL" : result.toString())); } /** * 定义一个异常通知函数: 只有在方法跑吹异常时,该方法才会执行,而且可以接受异常对象。 */ public void afterThrowingMethod(JoinPoint joinpoint, Exception ex) { String methodName = joinpoint.getSignature().getName(); List<Object> args = Arrays.asList(joinpoint.getArgs()); System.out.println( "after method " + methodName + " occurs exception: " + (ex == null ? "NULL" : ex.getMessage())); } public Object aroundMethod(ProceedingJoinPoint pJoinPoint) throws Exception { String methodName = pJoinPoint.getSignature().getName(); List<Object> args = Arrays.asList(pJoinPoint.getArgs()); Object result = null; try { // 前置通知 System.out.println("before method " + methodName + " with " + args); // 执行目标方法 result = pJoinPoint.proceed(); // 返回通知 System.out.println("after method " + methodName + " returning " + result); } catch (Throwable ex) { // 异常通知 System.out.println("after method " + methodName + " occurs exception: " + ex.getMessage()); throw new Exception(ex); } // 后置通知 System.out.println("after method " + methodName); return result; } }
ValidateAspect.java验证切面类:
package com.dx.spring.beans.xml; public class ValidateAspect { public void beforeMethod() { System.out.println("validate..."); } }
第三步:添加Spring配置文件spring-aop-xml.xml并配置AOP:
前置、后置、返回、异常通知配置:
<?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/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"> <!-- 定义 Bean --> <bean id="arithmeticCalculator" class="com.dx.spring.beans.xml.ArithmeticCalculatorImpl"></bean> <!-- 配置切面的Bean --> <bean id="loggingAspect" class="com.dx.spring.beans.xml.LoggingAspect"></bean> <bean id="validateAspect" class="com.dx.spring.beans.xml.ValidateAspect"></bean> <!-- 配置AOP --> <aop:config> <!-- 配置切入点表达式 --> <aop:pointcut expression="execution(* com.dx.spring.beans.xml.IArithmeticCalculator.*(..))" id="pointcut" /> <!-- 配置切面及通知 --> <aop:aspect ref="loggingAspect" order="2"> <!-- 配置前置、后置、返回、异常通知 --> <aop:before method="beforeMethod" pointcut-ref="pointcut" /> <aop:after method="afterMethod" pointcut-ref="pointcut" /> <aop:after-returning method="afterReturningMethod" pointcut-ref="pointcut" returning="result" /> <aop:after-throwing method="afterThrowingMethod" pointcut-ref="pointcut" throwing="ex" /> <!-- 配置环绕通知 --> <!--<aop:around method="aroundMethod" pointcut-ref="pointcut" /> --> </aop:aspect> <aop:aspect ref="validateAspect" order="1"> <aop:before method="beforeMethod" pointcut-ref="pointcut" /> </aop:aspect> </aop:config> </beans>
环绕配置:
<aop:around method="aroundMethod" pointcut-ref="pointcut" />
第四步:测试
前置、后置、返回、异常通知配置:
此时打印结果:
validate...
before method add with [1, 3]
after method add
after method add with returning 4
4
validate...
before method div with [4, 2]
after method div
after method div with returning 2
2
环绕配置:
此时打印结果:
validate...
before method add with [1, 3]
after method add returning 4
after method add
4
validate...
before method div with [4, 2]
after method div returning 2
after method div
2
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。