文章目录

  • 前言
  • 一、示例代码
  • 二、DynamicAdvisedInterceptor
  • 三、ReflectiveMethodInvocation

前言

前面简单的写了下Spring AOP中是怎么实现动态代理的,简单的来说是通过bean对象的后置管理器对实例化的bean对象做判断后使用不同的动态代理方式,下面来看一下生成的动态代理是怎么执行的。

一、示例代码

@Aspect
@Component
public class MyAspect {@Pointcut("execution(public void com.jack.service.TestService.doSomething())")public void point(){}@Before("point()")public void beforeMethod(JoinPoint joinPoint) {System.out.println("beforeMethod----");}@After("point()")public void afterMethod(JoinPoint joinPoint) {System.out.println("afterMethod----");}@AfterReturning("point()")public void AfterReturning() {System.out.println("AfterReturning----");}@AfterThrowing("point()")public void AfterThrowing() {System.out.println("AfterThrowing----");}@Around("point()")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("around start---");proceedingJoinPoint.proceed();System.out.println("around end---");}
}

多配置几个通知类型来观察一下这些通知之间是怎么协调调用的。

二、DynamicAdvisedInterceptor

CGLIB的动态代理主要是依靠MethodInterceptor来实现的,看一下AOP中CglibAopProxy类,在这个类里面有个内部类DynamicAdvisedInterceptor,仔细一看这个类它的父类是MethodInterceptor瞬间就清晰了,这就是最后CGLIB代理的执行类。

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {private final AdvisedSupport advised;public DynamicAdvisedInterceptor(AdvisedSupport advised) {this.advised = advised;}@Override@Nullablepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;//获取代理对象等属性一系列操作TargetSource targetSource = this.advised.getTargetSource();try {if (this.advised.exposeProxy) {oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);//获取任务调用链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;//进行了一系列判断,最终断点没走这if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);try {retVal = methodProxy.invoke(target, argsToUse);}catch (CodeGenerationException ex) {CglibMethodInvocation.logFastClassGenerationFailure(method);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}}else {//断点走了这里,当走完这一行发现打印完所有语句了,应该是在这里进行的调用retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}}...}

可以看到获取到的任务调用链就是我们写的那几个通知方法

在执行过程中我们定位到了执行代理方法的是这一行。

 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

三、ReflectiveMethodInvocation

CglibMethodInvocation的父类是ReflectiveMethodInvocation,这是最终执行的父类。
看一下其属性

 //代理类protected final Object proxy;protected final Object target;//被代理的方法切面protected final Method method; protected Object[] arguments;private final Class<?> targetClass;//这个打断点后发现里面存放的是切点private Map<String, Object> userAttributes;//这个是调用链protected final List<?> interceptorsAndDynamicMethodMatchers;//调用链坐标private int currentInterceptorIndex = -1;

可以看到上面的方法CGLIB调用操作最终是对其属性进行赋值。

protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {this.proxy = proxy;this.target = target;this.targetClass = targetClass;this.method = BridgeMethodResolver.findBridgedMethod(method);this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}

看一下该类的执行方法,很简单的操作

public Object proceed() throws Throwable {// 获取调用链的长度if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}//获取当前该执行的通知任务Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);//任务通知的动态匹配,断点没走这if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {return proceed();}}else {//最终断点走了elsereturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}

看断点的结果可以得出结论,代理任务中的多种代理方式都有一个对应的实现类,然后按照代理的顺序去调用不同的代理类。

随便看一个MethodBeforeAdviceInterceptor中的实现

public Object invoke(MethodInvocation mi) throws Throwable {//调用前置处理方法this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());//调用方法return mi.proceed();
}

其实在Spring中的动态代理最终的执行使用的是责任链设计模式。大家可以自己看一下JDK动态代理的实现方式,最终是一样的。

在这里教大家一个看源码的小技巧,假设我们对CglibMethodInvocation类不了解,不知道它的执行方法是哪个怎么办呢?我们点到了配置方法没有看到运行。
可以这样做,随便找个要执行的方法,例如before里面的打印,打个断点,然后看断点下面的方法调用链就可以找到源码中正在执行的方法了。

Spring AOP中的责任链设计模式相关推荐

  1. java责任链设计模式_Java中的责任链设计模式

    java责任链设计模式 在本教程中,我们将学习如何在Java中实现责任链模式. 责任链设计模式涉及到拥有一系列负责处理请求的对象链. 当客户端发送请求时,第一个处理程序将尝试处理该请求. 如果可以处理 ...

  2. Java中的责任链设计模式

    在本教程中,我们将学习如何在Java中实现责任链模式. "责任链"设计模式涉及到拥有一系列负责处理请求的对象链. 当客户端发送请求时,第一个处理程序将尝试处理该请求. 如果可以处理 ...

  3. spring aop实现过程之二Spring AOP中拦截器链

    1.开始步骤--获取AopProxy主流程 ProxyCreatorSupport.java /*** Subclasses should call this to get a new AOP pro ...

  4. 使用Spring @Autowired List的责任链

    在Spring 3.1中,有一种方法可以自动填充类型化的List,这在您想在代码中稍微进行去耦和清理时非常方便. 为了向您展示它是如何工作的,我将实现一个简单的责任链,该责任链将为通过的用户打印一些问 ...

  5. 责任链设计模式(过滤器、拦截器)

    责任链设计模式(Chain of Responsibility)的应用有:Java Web中的过滤器链.Struts2中的拦截器栈. 先看一个问题: 给定一个字符串"被就业了:),敏感信息, ...

  6. 设计模式示例_责任链设计模式示例

    设计模式示例 本文是我们名为" Java设计模式 "的学院课程的一部分. 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们. 您将了解模式如此重要的原因 ...

  7. java 职责链模式_Java中的责任链模式

    java 职责链模式 当应有几个处理器来执行某项操作并为这些处理器定义特定顺序时,就需要采用责任链设计模式. 在运行时处理器顺序的可变性也很重要.模式的UML表示如下: 处理程序定义处理器对象的一般结 ...

  8. Java中的责任链模式

    当应有几个处理器来执行某项操作并为这些处理器定义特定顺序时,就需要采用责任链设计模式. 在运行时处理器顺序的可变性也很重要.模式的UML表示如下: 处理程序定义处理器对象的一般结构. 这里的" ...

  9. 行为设计模式 - 责任链设计模式

    行为设计模式 - 责任链设计模式 责任链设计模式是行为设计模式之一. 目录[ 隐藏 ] 1责任链设计模式 1.1 JDK中的责任链模式示例 1.2责任链设计模式实例 1.3责任链设计模式 - 基类和接 ...

  10. 一文弄懂责任链设计模式

    目录 背景 什么是责任链 使用场景 结语 背景 最近,我让团队内一位成员写了一个导入功能.他使用了责任链模式,代码堆的非常多,bug 也多,没有达到我预期的效果. 实际上,针对导入功能,我认为模版方法 ...

最新文章

  1. 计算机网络:第三章 数据链路层
  2. 动态添加 ajax,ajax动态的添加内容【原创】
  3. Django create和save方法
  4. 《从零开始学ASP.NET CORE MVC》课程介绍
  5. Miller_Rabin算法
  6. 信息学奥赛一本通C++语言——1108: 向量点积计算
  7. ctfshow-萌新-web6( 利用二进制绕过获取网站敏感信息)
  8. mysql日期函数转换_Mysql日期函数大全 转
  9. SRAM,SDRAM,网卡
  10. java文件乱码 环境变量_JAVA安装后,环境变量的PATH被我改了,后来发现改错了,但是不知道怎么改回去了,就是一堆乱码的...
  11. Ubuntu20.04安装qt详细教程
  12. ARM指令集之跳转指令
  13. 开源BI工具对比(三) DataEase
  14. 公众号写作排版指南v2.0(适配Dark Mode)
  15. leapFTP上传网页到服务器,leapftp登录ftp服务器
  16. Java Web 2.1.4 HTML 表单标签与表单设计 (实例)
  17. OpenGL 渲染点GL_POINTS
  18. 软考网络工程师-华为交换机学习
  19. 面试经历---UC(2016年01月11日下午面试)
  20. 力扣 863. 二叉树中所有距离为 K 的结点

热门文章

  1. 一个好用的鼠标连点器
  2. STM32 USB Host 鼠标和键盘驱动 -- 原创
  3. 一个驱动级别的 键盘鼠标模拟工具
  4. Linux消息队列及函数详解(含示例)
  5. 安装vim及vim插件使用
  6. PR曲线以及ROC曲线的简单理解
  7. (ICPR-2021)使用胶囊的多尺度部分表示变换的步态识别
  8. 什么是探索性测试?探索性测试有哪些方法?
  9. OpenGL glut导入OBJ模型文件
  10. scara机器人动荷载_【机器人在线】SCARA机械结构参数计算说明 下