关关雎鸠,在河之洲。窈窕淑女,君子好逑。

概述

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

代码下载

代码下载

spring aop 之链式调用的更多相关文章

  1. 仿jQuery之链式调用

    链式调用的形式其实就是对象调用一连串的方法.为什么能连续调用这么多的方法?因为调用方法返回调用的对象,于是乎就可以一如既往,一往无前地调用下去.链式调用的原理就是在方法中返回执行上下文this,每次调 ...

  2. Javasript设计模式之链式调用

    写过jquery的可能都知道,jquery里面可以很方便的使用以下代码: // 不使用链式调用 const element = $(ele); element.addClass('red'); ele ...

  3. Jquery复习(三)之链式调用

    通过 jQuery,可以把动作/方法链接在一起. Chaining 允许我们在一条语句中运行多个 jQuery 方法(在相同的元素上). jQuery 方法链接 直到现在,我们都是一次写一条 jQue ...

  4. jquery之链式调用,层级菜单

    一. 链式调用的含义 jquery对象的方法会在执行完后返回这个jquery对象,所有jquery对象的方法可以连起来写: $('#div1') // id为div1的元素 .children('ul ...

  5. Spring AOP调用本类方法为什么没有生效

    首先请思考一下以下代码执行的结果: LogAop.java //声明一个AOP拦截service包下的所有方法@Aspectpublic class LogAop { @Around("ex ...

  6. Spring技术内幕:Spring AOP的实现原理(一)

    一.SpringAOP的概述 1.AOP概念 AOP是Aspect-Oriented Programming(面向切面编程)的简称.维基百科的解释例如以下: Aspect是一种新的模块化机制,用来描写 ...

  7. Spring AOP 问与答

    AOP的实现有哪些 AOP常见的实现有: Spring AOP Aspectj Guice AOP Jboss AOP 等 AOP Alliance 是什么, 为什么Spring AOP, G UIC ...

  8. Spring AOP 概述

    1. AOP的概念 AOP 是Aspect-Oriented Programming(面向方面编程或者面向切面)的简称,维基百科对其解释如下: Aspect是一种新的模块化机制,用来描述分散在对象.类 ...

  9. Spring技术内幕:Spring AOP的实现原理(三)

    生成SingleTon代理对象在getSingleTonInstance方法中完毕,这种方法时ProxyFactoryBean生成AopProxy对象的入口.代理对象会封装对target目标对象的调用 ...

随机推荐

  1. JVM调优前戏之JDK命令行工具---jhat

    在JDK的命令行中,一般开发人员最耳熟能详的肯定就是java,javac,javap等常用命令,不过在jdk/bin下还有许多其他的命令行工具,它们被用来监测JVM运行时的状态,下面我们来详细解读一下 ...

  2. 【记忆化搜索】掷骰子 hpuoj

    B. 掷骰子 单点时限: 2.0 sec 内存限制: 512 MB 骰子,中国传统民间娱乐用来投掷的博具,早在战国时期就已经被发明. 现在给你 n 个骰子,求 n 个骰子掷出点数之和为 a 的概率是多 ...

  3. Spring Cloud Gateway 服务网关快速上手

    Spring Cloud Gateway 服务网关 API 主流网关有NGINX.ZUUL.Spring Cloud Gateway.Linkerd等:Spring Cloud Gateway构建于 ...

  4. 开源题材征集 + MVC&EF Core 完整教程小结

    到目前为止,我们的MVC+EF Core 完整教程的理论部分就全部结束了,共20篇,覆盖了核心的主要知识点. 下一阶段是实战部分,我们将会把这些知识点串联起来,用10篇(天)来完成一个开源项目. 现向 ...

  5. SSH原理讲解与实践

    一.简介 SSH全名Secure Socket Shell,安全外壳传输协议.专为远程登录会话和其他网络服务提供安全性的协议 二.加密算法 要了解SSH的原理,就要先知道目前主流的俩种加密算法 2.1 ...

  6. [HAOI2015]树上染色(树上dp)

    [HAOI2015]树上染色 这种要算点对之间路径的长度和的题,难以统计每个点的贡献.这个时候一般考虑算每一条边贡献了哪些点对. 知道这个套路以后,那么这题就很好做了. 状态:设\(dp[u][i]\ ...

  7. 【2017cs231n】:课程笔记-第2讲:图像分类

    [2017cs231n]:课程笔记-第2讲:图像分类 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.n ...

  8. Codeforces 985D

    题意略. 思路:这个题本来打算先推一下公式,然后解方程来算.函数图像大概如下: 最左端为H.但是由于中间那个尖的地方(假设它的高度为h),可能在那个地方有多堆沙包,所以推公式貌似不行. 但是最高高度h ...

  9. Javaweb之文件的上传与下载

    Javaweb之文件的上传与下载 一.基于表单的文件上传 如果在表单中使用表单元素 <input type=“file” />,浏览器在解析表单时,会自动生成一个输入框和一个按钮,输入框可 ...

  10. ASP.NET Core 2.2 : 二十七. JWT与用户授权(细化到Action)

    上一章分享了如何在ASP.NET Core中应用JWT进行用户认证以及Token的刷新,本章继续进行下一步,用户授权.涉及到的例子也以上一章的为基础.(ASP.NET Core 系列目录) 一.概述 ...