0:Spring AOP 原理

简单说说 AOP 的设计:

  1. 每个 Bean 都会被 JDK 或者 Cglib 代理。取决于是否有接口。

  2. 每个 Bean 会有多个“方法拦截器”。注意:拦截器分为两层,外层由 Spring 内核控制流程,内层拦截器是用户设置,也就是 AOP。

  3. 当代理方法被调用时,先经过外层拦截器,外层拦截器根据方法的各种信息判断该方法应该执行哪些“内层拦截器”。内层拦截器的设计就是职责连的设计。

可以将 AOP 分成 2 个部分:

第一:代理的创建;

第二:代理的调用。

开始分析(扯):

  1. 代理的创建(按步骤):

  • 首先,需要创建代理工厂,代理工厂需要 3 个重要的信息:拦截器数组,目标对象接口数组,目标对象。

  • 创建代理工厂时,默认会在拦截器数组尾部再增加一个默认拦截器 —— 用于最终的调用目标方法。

  • 当调用 getProxy 方法的时候,会根据接口数量大余 0 条件返回一个代理对象(JDK or  Cglib)。

  • 注意:创建代理对象时,同时会创建一个外层拦截器,这个拦截器就是 Spring 内核的拦截器。用于控制整个 AOP 的流程。

  1. 代理的调用

  • 当对代理对象进行调用时,就会触发外层拦截器。

  • 外层拦截器根据代理配置信息,创建内层拦截器链。创建的过程中,会根据表达式判断当前拦截是否匹配这个拦截器。而这个拦截器链设计模式就是职责链模式。

  • 当整个链条执行到最后时,就会触发创建代理时那个尾部的默认拦截器,从而调用目标方法。最后返回。

Spring对AOP的支持

Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:

1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了

2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB

AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:

1、定义普通业务组件

2、定义切入点,一个切入点可能横切多个业务组件

3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作

所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。

1:知识背景

软件系统可以看成是由一组关注点组成的,其中,直接的业务关注点,是直切关注点。而为直切关注点提供服务的,就是横切关注点。

2:面向切面的基本原理

什么是面向切面编程

横切关注点:影响应用多处的功能(安全、事务、日志)

切面:

横切关注点被模块化为特殊的类,这些类称为切面

优点:

每个关注点现在都集中于一处,而不是分散到多处代码中 
服务模块更简洁,服务模块只需关注核心代码。

AOP 术语

  • 通知:

    • 定义:切面也需要完成工作。在 AOP 术语中,切面的工作被称为通知。
    • 工作内容:通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还解决何时执行这个工作。
    • Spring 切面可应用的 5 种通知类型:
  1. Before——在方法调用之前调用通知
  2. After——在方法完成之后调用通知,无论方法执行成功与否
  3. After-returning——在方法执行成功之后调用通知
  4. After-throwing——在方法抛出异常后进行通知
  5. Around——通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
  • 连接点:

    • 定义:连接点是一个应用执行过程中能够插入一个切面的点。
    • 连接点可以是调用方法时、抛出异常时、甚至修改字段时、
    • 切面代码可以利用这些点插入到应用的正规流程中
    • 程序执行过程中能够应用通知的所有点。
  • 切点: 
    • 定义:如果通知定义了“什么”和“何时”。那么切点就定义了“何处”。切点会匹配通知所要织入的一个或者多个连接点。
    • 通常使用明确的类或者方法来指定这些切点。
    • 作用:定义通知被应用的位置(在哪些连接点)
  • 切面: 
    • 定义:切面是通知和切点的集合,通知和切点共同定义了切面的全部功能——它是什么,在何时何处完成其功能。
  • 引入: 
    • 引入允许我们向现有的类中添加方法或属性
  • 织入: 
    • 织入是将切面应用到目标对象来创建的代理对象过程。
    • 切面在指定的连接点被织入到目标对象中,在目标对象的生命周期中有多个点可以织入
  1. 编译期——切面在目标类编译时期被织入,这种方式需要特殊编译器。AspectJ的织入编译器就是以这种方式织入切面。
  2. 类加载期——切面在类加载到
  3. JVM ,这种方式需要特殊的类加载器,他可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5 的 LTW 就支持这种织入方式
  4. 运行期——切面在应用运行期间的某个时刻被织入。一般情况下,在织入切面时候,AOP 容器会为目标对象动态的创建代理对象。Spring AOP 就是以这种方式织入切面。

3:Spring 对 AOP 的支持

  • 并不是所有的 AOP 框架都是一样的,他们在连接点模型上可能有强弱之分。

    • 有些允许对字段修饰符级别应用通知
    • 有些支持方法调用连接点
  • Spring 提供的 4 种各具特色的 AOP 支持
  1. 基于代理的经典 AOP;
  2. @AspectJ 注解驱动的切面;
  3. 纯 POJO 切面;
  4. 注入式 AspectJ 切面; Spring
  • 在运行期间通知对象

    • 通过在代理类中织入包裹切面,Spring 在运行期间将切面织入到 Spring 管理的 Bean 中。 
      代理类封装了目标类,并拦截被通知的方法调用,再将调用转发给真正的目标 Bean

      当拦截到方法调用时,在调用目标 Bean 方法之前,代理会执行切面逻辑。 
      当真正应用需要被代理的 Bean 时,Spring 才创建代理对象。如果使用 ApplicationContext,在 ApplicationContext 从 BeanFactory 中加载所有 Bean 时,Spring 创建代理对象,因为 Spring 在运行时候创建代理对象,所以我们不需要特殊的编译器来织入 Spring AOP 的切面。

  • Spring 支持方法创建连接点 
    • 因为 Spring 基于动态代理,所以 Spring 只支持方法连接点。
    • Spring 缺失对字段连接点的支持,无法让我们更加细粒度的通知,例如拦截对象字段的修改
    • Spring 缺失对构造器连接点支持,我发在 Bean 创建时候进行通知。

4:使用切点选择连接点

  • 切点用于准确定位,确定在什么地方应用切面通知。
  • Spring 定义切点 
    • 在 Spring AOP 中,需要使用 AspectJ 的切点表达式来定义切点。
AspectJ 指示器 描述
arg () 限制连接点的指定参数为指定类型的执行方法
@args () 限制连接点匹配参数由指定注解标注的执行方法
execution () 用于匹配连接点的执行方法
this () 限制连接点匹配 AOP 代理的 Bean 引用为指定类型的类
target () 限制连接点匹配特定的执行对象,这些对象对应的类要具备指定类型注解
within() 限制连接点匹配指定类型
@within() 限制连接点匹配指定注释所标注的类型(当使用 Spring AOP 时,方法定义在由指定的注解所标注的类里)
@annotation 限制匹配带有指定注释的连接点

1. 创建自己的切点

- execution( ) 指示器选择 Instrument 的 play( ) 方法。 
方法表达式是以 * 号开头,标识了我们不关心的方法返回值的类型。 
* 后我们指定了权限定类名和方法名。 
对于方法的参数列表,使用(..)标识切点选择任意的 play( ) 方法,无论入参是什么。 
- 假设我们需要匹配切点仅匹配 com.Springinaction.springidol 包。可以使用 within()

注意 && 是将 execution( ) 和 within( ) 连接起来,形成的 and 关系。同理也可以使用 || 或关系、!非关系 
- 创建 Spring 的 bean( ) 指示器 
Spring 2.5 引入一个新的 bean( ) 指示器,该指示器允许我们在切点表达式中使用 Bean ID 来标识 Bean 
bean( ) 使用 Bean ID 或 Bean 名称作为参数来限制切点只匹配特定 Bean。 
如下,我们希望执行 Instrument 的 play( ) 方法时候应用通知,但限定 Bean 的 ID 为 eddie

还可以使用非操作作为除了指定 ID 的 Bean 以外的其他 Bean应用通知

在此场景下,切面会通知被编织到所有 ID 不为 eddie 的 Bean 中

5:在 XML 中声明切面

Spring 的 AOP 配置元素简化了基于 POJO 切面声明

AOP 配置元素

描述
aop : advisor 定义 AOP 通知器
aop : after 定义 AOP 后置通知(不管被通知方法是否执行成功)
aop : after-returing 定义 AOP after-returing 通知
aop : after-throwing 定义 AOP after-throwing 通知
aop : around 定义 AOP 环绕通知
aop : aspect 定义切面
aop : aspectj-autoproxy 启动 @AspectJ 注解驱动的切面
aop : before 定义 AOP 前置通知
aop : config 顶层的 AOP 配置元素,大多数 aop : * 元素必须包含在 元素内
aop : declare-parents 为被通知的对象引入额外接口,并透明的实现
aop : pointcut 定义切点

参考来源:http://blog.csdn.net/github_34889651/article/details/51321499

Spring AOP:原理、 通知、连接点、切点、切面、表达式相关推荐

  1. 史上最烂 spring aop 原理分析

    盗引·中篇·spring aop spring aop: jdk 动态代理和 cglib 动态代理的特点.区别.使用方式.原理及各自对反射的优化.二者在 spring 中的统一.通知顺序.从 @Asp ...

  2. modelandview使用过程_面试问烂的 Spring AOP 原理、Spring MVC 过程

    点击上方 Java后端,选择 设为星标 优质文章,及时送达 作者:莫那一鲁道链接:www.jianshu.com/p/e18fd44964eb Spring AOP ,SpringMVC ,这两个应该 ...

  3. 面试问烂的 Spring AOP 原理、SpringMVC 过程(求求你别问了)

    Spring AOP ,SpringMVC ,这两个应该是国内面试必问题,网上有很多答案,其实背背就可以.但今天笔者带大家一起深入浅出源码,看看他的原理.以期让印象更加深刻,面试的时候游刃有余. Sp ...

  4. Spring AOP之通知类别

    什么是通知类别 通知在切入点中执行的位置就是通知类别.关于通知和通知类别具体概念请移步我的另一篇博客Spring AOP之HelloWorld与概念介绍 5种通知类别介绍 在Spring AOP 中通 ...

  5. Spring AOP 之 通知、连接点、切点、切面。

    1:知识背景 软件系统可以看成是由一组关注点组成的,其中,直接的业务关注点,是直切关注点.而为直切关注点提供服务的,就是横切关注点. 2:面向切面的基本原理 什么是面向切面编程 横切关注点:影响应用多 ...

  6. Spring AOP(通知、连接点、切点、切面)

    一.AOP术语 通知(Advice)   切面的工作被称为通知.通知定义了切面是什么以及何时使用.除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题. 5种通知类型: 前置通知(Before ...

  7. Spring(十九):Spring AOP(三):切面的优先级、重复使用切入点表达式

    背景: 1)指定切面优先级示例:有的时候需要对一个方法指定多个切面,而这多个切面有时又需要按照不同顺序执行,因此,切面执行优先级别指定功能就变得很实用. 2)重复使用切入点表达式:上一篇文章中,定义前 ...

  8. Spring原理学习系列之三:Spring AOP原理(从源码层面分析)-------上部

    引言 本文是Spring原理分析的第三篇博文,主要阐述Spring AOP相关概念,同时从源码层面分析AOP实现原理.对于AOP原理的理解有利于加深对Spring框架的深入理解.同时我也希望可以探究S ...

  9. 全网最好懂的Spring AOP原理

    1 AOP概念 AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善. AOP ...

  10. Spring AOP原理及使用,面试必备

    a) 什么是AOP? AOP(Aspect Oriented Programming),也就是面向切面编程,是对面向对象编程OOP的一种补充:通过"横切"技术剖解开封装的对象内部, ...

最新文章

  1. 关于学习编程的一些看法
  2. 陆奇要离职?先看看百度财报吧
  3. eplise怎么连接数据库_如何通过eclipse连接到mysql数据库
  4. [转]open channel SSD FTL
  5. java 对象的属性_java-更新对象属性
  6. 浅析网络流量分析原理:如何把二进制“天书”变成“人话”
  7. C语言家谱管理程序,课内资源 - 基于C语言实现的家谱管理系统
  8. 前端学习(3121):react-hello-react的state的简写方式
  9. MyBatis 在xml文件中处理大于号小于号的方法
  10. Android 广播接收
  11. 电力企业信息化建设解决方案之计量生产分析系统
  12. 计算机重启恢复到推荐分辨率,为什么重启之后电脑界面分辨率会变
  13. SQL数据库置疑修复
  14. Unity插入视频音频
  15. Delphi好书推荐
  16. [黑苹果]炫龙毁灭者DC显卡无解
  17. 三节点大数据环境安装教程1
  18. 《信息物理融合系统(CPS)设计、建模与仿真——基于 Ptolemy II 平台》——2.3 层次结构和复合角色...
  19. 用JSP构建三层管理信息系统
  20. border样式失效原因

热门文章

  1. 【C语言】已知三角形三边长,求三角形面积
  2. NFM模型理论与实践
  3. shell in find exclude
  4. 视频文件(任意文件)二进制读写
  5. ffmpeg 合并拼接 mp4视频
  6. iOS开发调试技巧之在App设置中切换服务器环境
  7. 重学TCP协议(8) TCP的11种状态
  8. 简支梁模型振动位移matlab,不同移动载荷速度下简支桥梁的变形及振动响应研究...
  9. 手机如何测光照度_另类玩法:手机变身照度计
  10. Java分解整型质因数