spring aop之链式调用的实现

 更新时间:2019年02月20日 10:18:19   作者:niocoder  
这篇文章主要介绍了spring aop之链式调用的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

概述

AOPAspect 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

实现MethodInvocationproceed()方法递归实现链式调用。

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Spring boot实现文件上传功能

    Spring boot实现文件上传功能

    这篇文章主要为大家详细介绍了Spring boot实现文件上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • 在jmeter的beanshell中用java获取系统当前时间的简单实例

    在jmeter的beanshell中用java获取系统当前时间的简单实例

    这篇文章介绍了在jmeter的beanshell中用java获取系统当前时间的简单实例,有需要的朋友可以参考一下
    2013-09-09
  • 基于Spring实现文件上传功能

    基于Spring实现文件上传功能

    这篇文章主要为大家详细介绍了Spring实现文件上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • springAop实现讲解(看这篇够了)

    springAop实现讲解(看这篇够了)

    AOP面向切面编程是一种编程范式,它通过将通用的横切关注点(如日志、事务、权限控制等)与业务逻辑分离,使得代码更加清晰、简洁、易于维护,这篇文章主要介绍了springAop实现讲解(看这篇够了),需要的朋友可以参考下
    2024-02-02
  • java中静态变量和实例变量的区别详细介绍

    java中静态变量和实例变量的区别详细介绍

    本篇文章介绍了,java中静态变量和实例变量的区别。需要的朋友参考下
    2013-05-05
  • Java使用easyExcel批量导入数据详解

    Java使用easyExcel批量导入数据详解

    这篇文章主要介绍了Java使用easyExcel批量导入数据详解,通常我们会提供一个模板,此模块我们可以使用easyExcel导出数据生成的一个Excel文件当作模板,提供下载链接,用户在该文件内填入规定的数据格式以后可以批量导入数据到数据库中,需要的朋友可以参考下
    2023-08-08
  • mybatis 连接mysql数据库 tinyint 为boolean类型详解

    mybatis 连接mysql数据库 tinyint 为boolean类型详解

    这篇文章主要介绍了mybatis 连接mysql数据库 tinyint 为boolean类型详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • SpringBoot容器的主要组件详解

    SpringBoot容器的主要组件详解

    这篇文章主要介绍了SpringBoot容器的主要组件详解,SpringBoot 是基于 Spring Framework 的一种快速开发框架,它可以帮助开发者快速地构建独立的、生产级别的、可部署的应用程序,需要的朋友可以参考下
    2023-09-09
  • java 实现取int型的第二个字节的数

    java 实现取int型的第二个字节的数

    这篇文章主要介绍了java 实现取int型的第二个字节的数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 详解Java中的JDK、JRE、JVM

    详解Java中的JDK、JRE、JVM

    本文主要介绍了Java中的JDK、JRE、JVM的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-01-01

最新评论