spring aop之链式调用的实现
作者:niocoder
概述
AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、缓存等等。 Spring AOP采用的是动态代理,在运行期间对业务方法进行增强,所以不会生成新类,Spring AOP提供了对JDK动态代理的支持以及CGLib的支持。本章我们不关注aop代理类的实现,我简单实现一个指定次序的链式调用。
实现链式调用的
MethodInterceptor定义拦截器链,MethodInvocation 递归进入下一个拦截器链中。类图如下:

MethodInterceptor
public interface MethodInterceptor {
  Object invoke(MethodInvocation invocation) throws Throwable;
}
MethodInvocation
public interface MethodInvocation {
  Object proceed() throws Throwable;
}
AbstractAspectJAdvice
抽象类,实现MethodInterceptor
public abstract class AbstractAspectJAdvice implements MethodInterceptor{
  private Method adviceMethod;
  private Object adviceObject;
  public AbstractAspectJAdvice(Method adviceMethod, Object adviceObject) {
    this.adviceMethod = adviceMethod;
    this.adviceObject = adviceObject;
  }
  public Method getAdviceMethod() {
    return this.adviceMethod;
  }
  public void invokeAdviceMethod() throws Throwable {
    adviceMethod.invoke(adviceObject);
  }
}
AspectJBeforeAdvice
前置通知
public class AspectJBeforeAdvice extends AbstractAspectJAdvice {
  public AspectJBeforeAdvice(Method method, Object adviceObject) {
    super(method, adviceObject);
  }
  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable{
    this.invokeAdviceMethod();
    Object o = invocation.proceed();
    return o;
  }
}
AspectJAfterReturningAdvice
后置通知
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice {
  public AspectJAfterReturningAdvice(Method method, Object adviceObject) {
    super(method, adviceObject);
  }
  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable{
    Object o = invocation.proceed();
    this.invokeAdviceMethod();
    return o;
  }
}
ReflectiveMethodInvocation
实现MethodInvocation,proceed()方法递归实现链式调用。
public class ReflectiveMethodInvocation implements MethodInvocation {
  private final Object targetObject;
  private final Method targetMethod;
  private final List<MethodInterceptor> interceptorList;
  private int currentInterceptorIndex = -1;
  public ReflectiveMethodInvocation(Object targetObject, Method targetMethod, List<MethodInterceptor> interceptorList) {
    this.targetObject = targetObject;
    this.targetMethod = targetMethod;
    this.interceptorList = interceptorList;
  }
  @Override
  public Object proceed() throws Throwable {
    if (this.currentInterceptorIndex == this.interceptorList.size() - 1) {
      return invokeJoinPoint();
    }
    this.currentInterceptorIndex++;
    MethodInterceptor interceptor =
        this.interceptorList.get(this.currentInterceptorIndex);
    return interceptor.invoke(this);
  }
  private Object invokeJoinPoint() throws Throwable {
    return this.targetMethod.invoke(this.targetObject);
  }
}
NioCoderService
模拟service类
public class NioCoderService {
  public void testAop() {
    System.out.println("http://niocoder.com/");
  }
}
TransactionManager
模拟通知类
public class TransactionManager {
  public void start() {
    System.out.println("start tx");
  }
  public void commit() {
    System.out.println("commit tx");
  }
  public void rollback() {
    System.out.println("rollback tx");
  }
}
ReflectiveMethodInvocationTest
beforeAdvice->afterReturningAdvice
测试类,测试通知
public class ReflectiveMethodInvocationTest {
  private AspectJBeforeAdvice beforeAdvice = null;
  private AspectJAfterReturningAdvice afterReturningAdvice = null;
  private NioCoderService nioCoderService;
  private TransactionManager tx;
  public void setUp() throws Exception {
    nioCoderService = new NioCoderService();
    tx = new TransactionManager();
    beforeAdvice = new AspectJBeforeAdvice(TransactionManager.class.getMethod("start"), tx);
    afterReturningAdvice = new AspectJAfterReturningAdvice(TransactionManager.class.getMethod("commit"), tx);
  }
  public void testMethodInvocation() throws Throwable {
    Method method = NioCoderService.class.getMethod("testAop");
    List<MethodInterceptor> interceptorList = new ArrayList<>();
    interceptorList.add(beforeAdvice);
    interceptorList.add(afterReturningAdvice);    
    ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, method, interceptorList);
    mi.proceed();
  }
  public static void main(String[] args) throws Throwable {
    ReflectiveMethodInvocationTest reflectiveMethodInvocationTest = new ReflectiveMethodInvocationTest();
    reflectiveMethodInvocationTest.setUp();
    reflectiveMethodInvocationTest.testMethodInvocation();
  }
}
输出:
start tx
http://niocoder.com/
commit tx
时序图 beforeAdvice->afterReturningAdvice


afterReturningAdvice->beforeAdvice
修改interceptorList的顺序
public void testMethodInvocation() throws Throwable {
    Method method = NioCoderService.class.getMethod("testAop");
    List<MethodInterceptor> interceptorList = new ArrayList<>();
    interceptorList.add(afterReturningAdvice);
     interceptorList.add(beforeAdvice);
    ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, method, interceptorList);
    mi.proceed();
  }
输出:
start tx
http://niocoder.com/
commit tx
时序图 afterReturningAdvice->beforeAdvice


代码下载
github:https://github.com/longfeizheng/data-structure-java/blob/master/src/main/java/cn/merryyou/aop
代码下载
github:https://github.com/longfeizheng/data-structure-java
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
