之前实现的AOP都是基于注解方式的,下面开始使用配置文件方式配置AOP:
目标对象 —— 计算器类
- 接口:
package com.spring.aop.xml;
public interface Calculator {
int add(int i,int j);
int sub(int i,int j);
int div(int i,int j);
}
- 实现类:
package com.spring.aop.xml;
public class CalculatorImpl implements Calculator{
@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 div(int i, int j) {
int result = i / j;
return result;
}
}
完全纯净,不包含而外功能代码,只包含自己功能的核心代码。
- LoggingAspect —— 切面类:
package com.spring.aop.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){
//注意,JoinPoint来自org.aspectj.lang.JoinPoint,小心导错包
//执行方法名
String methodName = joinPoint.getSignature().getName();
//执行方法参数
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("前置通知:method 【"+methodName+"】,args:"+args);
}
//后置通知
public void afterMethod(JoinPoint joinPoint){
//执行方法名
String methodName = joinPoint.getSignature().getName();
//执行方法参数
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("后置通知:method 【"+methodName+"】,args:"+args);
}
//返回通知
public void afterReturning(JoinPoint joinPoint){
//执行方法名
String methodName = joinPoint.getSignature().getName();
//执行方法参数
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("返回通知:method 【"+methodName+"】 ,args:"+args);
}
//异常通知
public void afterThrowing(JoinPoint joinPoint,Exception ex){
//执行方法名
String methodName = joinPoint.getSignature().getName();
//执行方法参数
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("异常通知:method 【"+methodName+"】 ,args:"+args+",异常:"+ex);
}
//环绕通知
public Object around(ProceedingJoinPoint pjd){
Object result = null;
//执行方法名
String methodName = pjd.getSignature().getName();
//执行方法参数
List<Object> args = Arrays.asList(pjd.getArgs());
try {
//前置通知
System.out.println("前置通知:method 【"+methodName+"】 begin:"+args);
//执行方法
result = pjd.proceed();
System.out.println("返回通知:method 【"+methodName+"】 result:"+result);
} catch (Throwable ex) {
//异常通知
System.out.println("异常通知:method 【"+methodName+"】 end:"+ ex);
}
//后置通知
System.out.println("后置通知:method 【"+methodName+"】 end:"+args);
return result;
}
}
现在这个只是个普通的类,还没有配置为一个切面。
- 配置文件:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置bean -->
<bean id="calculatorImpl" class="com.spring.aop.xml.CalculatorImpl"></bean>
<!-- 配置切面bean -->
<bean id="loggingAspect" class="com.spring.aop.xml.LoggingAspect"></bean>
<aop:config>
<!-- 配置切点表达式 -->
<aop:pointcut expression="execution(* com.spring.aop.xml.CalculatorImpl.*(..))" 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="afterReturning" pointcut-ref="pointcut" returning="result"/>
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"/>
<!-- 环绕通知
<aop:around method="around" pointcut-ref="pointcut"/>
-->
</aop:aspect>
<!-- 可以配置多个切面
<aop:aspect>
...
</aop:aspect>
-->
</aop:config>
</beans>
配置AOP的一般步骤:
- 创建目标类的bean,将之交给spring容器管理。
- 创建切面类的bean,在后面的配置中会用到。
- 上面两个只是前提条件,下面开始正式配置AOP:
1). 配置切点 —— 通知作用的目标方法
2). 配置切面:先引用之前配置的切面bean,然后开始配置各种通知。
正常情况下, 基于注解的声明要优先于基于 XML 的声明. 通过 AspectJ 注解, 切面可以与 AspectJ 兼容, 而基于 XML的配置则是 Spring 专有的. 由于 AspectJ 得到越来越多的 AOP 框架支持, 所以以注解风格编写的切面将会有更多重用的机会.
本系列参考视频教程: http://edu.51cto.com/course/1956.html