首先举一个例子:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {private MethodBeforeAdvice advice;/*** Create a new MethodBeforeAdviceInterceptor for the given advice.* @param advice the MethodBeforeAdvice to wrap*/public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}//这个invoke方法是拦截器的回调方法,会在代理对象的方法被调用时触发回调@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {//首先触发advise的before回调this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );//然后才是MethodInvocation的proceed方法调用return mi.proceed();}}

上面是MethodBeforeAdviceInterceptor拦截器的源码,MethodBeforeAdvice是对应的通知,另外还有一个角色类是MethodBeforeAdviceAdapter适配器类,这个适配器的源码如下:

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {@Overridepublic boolean supportsAdvice(Advice advice) {return (advice instanceof MethodBeforeAdvice);}@Overridepublic MethodInterceptor getInterceptor(Advisor advisor) {MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();return new MethodBeforeAdviceInterceptor(advice);}}

可以看到,它的主要作用是,将通知advisor.getAdvice()转换或者说适配成对应的拦截器,有如下三种适配:

1. MethodBeforeAdviceAdapter将MethodBeforeAdvice适配成MethodBeforeAdviceInterceptor
2. AfterReturningAdviceAdapter将AfterReturningAdvice适配成AfterReturningAdviceInterceptor
3.ThrowsAdviceAdapter将ThrowsAdvice适配成ThrowsAdviceInterceptor

这样适配的目的是什么呢?

还得回到我们最初的MethodBeforeAdviceInterceptor的源码中去看

首先我们得知道通知是什么,通知就是在调用目标方法之前或者之后等要被调用的增强的方法,比如这里的MethodBeforeAdvice的before方法需要在调用目标方法之前被调用,AfterReturningAdvice的afterReturning方法需要在目标方法被调用之后调用,这个调用逻辑(调用顺序)就是由通知对应的拦截器来完成的,可以看到MethodBeforeAdviceInterceptor由于是前置通知的适配器,所以它的invoke方法在执行下一个拦截器的时候先调用了通知的before方法,然后进入到了下一个拦截器。

也就是说,通知只是定义了增强时将要被调用的方法,而方法具体何时调用需要由通知对应的拦截器来进行管理,而适配器的作用就是根据通知得到其对应的拦截器

再可以看看AfterReturningAdviceInterceptor拦截器

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {private final AfterReturningAdvice advice;/*** Create a new AfterReturningAdviceInterceptor for the given advice.* @param advice the AfterReturningAdvice to wrap*/public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}}

这个后置通知拦截器就是在先进入到下一个拦截器后,然后再调用的对应通知AfterReturningAdvice的afterReturning方法

所以我们可以看到,这几个拦截器实现的功能其实非常类似于动态代理设计模式里面实现了InvocationHandler接口的那个类,比如如下:

public class ProxyHandler implements InvocationHandler {private Object target;public ProxyHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("call before target");Object proxyObject = method.invoke(target, args);   //这里是要调用目标对象target的目标方法methodSystem.out.println("call after target");return proxyObject;}
}

这里目标target的方法被调用前,会被这个类的invoke方法拦截,method.invoke(target, args) 是调用目标方法,这里可以在其前后做一些增强方法

Spring源码分析之Aop中拦截器,适配器,通知之间的关系相关推荐

  1. Spring 源码分析(三) —— AOP(五)创建代理

    2019独角兽企业重金招聘Python工程师标准>>> 创建代理 代理的定义其实非常简单,就是改变原来目标对象方法调用的运行轨迹.这种改变,首先会对这些方法进行拦截,从而为这些方法提 ...

  2. Spring 源码分析(三) —— AOP(二)Spring AOP 整体架构

    2019独角兽企业重金招聘Python工程师标准>>> Spring AOP 架构         先是生成代理对象,然后是拦截器的作用,最后是编织的具体实现.这是AOP实现的三个步 ...

  3. Spring源码分析之AOP源码分析

    文章目录 前言 一.AOP回顾 二.源码分析 EnableAspectJAutoProxy注解 AnnotationAwareAspectJAutoProxyCreator 前言 Spring框架的两 ...

  4. spring源码分析之Aop

    今天读spring源码,读到aop相关内容,在此记录一下,以便以后复习和查阅. 一.spring如何实现Aop 这里简单的说下原理,spring实例化bean要经历一套完整的生命周期,在这个过程中会对 ...

  5. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

  6. Spring 源码分析(四) ——MVC(二)概述

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) from:Spring 源码分析(四) --MVC(二)概述 - 水门-kay的个人页面 - OSCHINA ...

  7. spring源码分析之spring-core总结篇

    1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...

  8. spring源码分析第六天------spring经典面试问题

    spring源码分析第六天------spring经典面试问题 1.Spring5 新特性及应用举例 2.Spring 经典的面试问题 a.什么是 Spring 框架?Spring 框架有哪些主要模块 ...

  9. spring源码分析第五天------springAOP核心原理及源码分析

    spring源码分析第五天------springAOP核心原理及源码分析 1. 面向切面编程.可以通过预 编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术 切面(A ...

最新文章

  1. 吉大20春学期C语言程序设计作业二,吉大18春学期《C语言程序设计》在线作业二【答案】...
  2. ScrollView反弹效果
  3. LeakCanary——直白的展现Android中的内存泄露
  4. python做后端开发的优点_【后端开发】python语言的特点是什么
  5. tortoiseGit的SHH秘钥设置
  6. 基于JAVA+SpringMVC+Mybatis+MYSQL的外卖点餐系统
  7. 【王道计组笔记】总线(2):性能指标分析
  8. 腾讯云TRTCCalling实时音视频说明文档
  9. 怎样用photoshop放大图片可以不失真的方法
  10. win10系统的计算机C盘在哪,c盘users在哪(win10c盘找不到users)
  11. 惠普打印机 HP web 服务打不开
  12. 马化腾,直接把360做特了!
  13. 因ubuntu内核升级导致的显卡驱动问题的解决方案
  14. html飘窗效果,js实现网页飘窗效果-Javascript-舒彬琪博客|前端技术博客|CMS教程|PbootCMS|JizhiCMS-www.cnsbq.com...
  15. CX3 调试学习_持续更新(此文大部分对于初步使用没啥用,回头去公众号整理一个精简版配置应用教程)
  16. Python paromiko每日生活学习感悟(第一次写,紧张hahaha)
  17. 游戏行业网页整站模板下载_游戏 整站 高光 传奇 黑色
  18. 传奇私服服务器怎么增加npc,在自己的传奇服务器中如何添加NPC
  19. C语言除法”四舍五入“与“进一法”的实现
  20. Spring的IOC和AOP课堂笔记

热门文章

  1. JAVA单例模式 关于延迟加载问题
  2. MyEclipse项目无法自动编译解决方案
  3. 万圣节后的早晨九数码游戏——双向广搜
  4. bzoj4009: [HNOI2015]接水果(整体二分)
  5. NVIDIA驱动瘫痪再重装的问题
  6. HDU 5491 The Next
  7. 递推+矩阵快速幂 HDU 2065
  8. 【转】Android之apk文件签名——keytool 和 jarsigner
  9. php 错误500排错,如何排查Web服务器HTTP ERROR 500的错误?
  10. stats | 数据降维之主成分分析(PCA)