之 横切关注点、通知、切点、链接点、引入、织入、建立切点

  1. 知识背景
    1. 软件系统能够当作是由一组关注点组成的,其中,直接的业务关注点,是直切关注点。而为直切关注点提供服务的,就是横切关注点。

  2. 面向切面的基本原理
    1. 什么是面向切面编程
      1. 横切关注点:影响应用多处的功能(安全、事务、日志)
      2. 切面:横切关注点被模块化为特殊的类,这些类称为切面
        1. 优势:
          每一个关注点如今都集中于一处,而不是分散到多处代码中
          服务模块更简洁,服务模块只需关注核心代码。
    2. AOP 术语

      1. 通知:
        1. 定义:切面也须要完成工做。在 AOP 术语中,切面的工做被称为通知。
        2. 工做内容:通知定义了切面是什么以及什么时候使用。除了描述切面要完成的工做,通知还解决什么时候执行这个工做。
        3. Spring 切面可应用的 5 种通知类型:
          Before——在方法调用以前调用通知
          After——在方法完成以后调用通知,不管方法执行成功与否
          After-returning——在方法执行成功以后调用通知
          After-throwing——在方法抛出异常后进行通知
          Around——通知包裹了被通知的方法,在被通知的方法调用以前和调用以后执行自定义的行为
      2. 链接点:
        1. 定义:链接点是一个应用执行过程当中可以插入一个切面的点。
        2. 链接点能够是调用方法时、抛出异常时、甚至修改字段时、
        3. 切面代码能够利用这些点插入到应用的正规流程中
        4. 程序执行过程当中可以应用通知的全部点。
      3. 切点:
        1. 定义:若是通知定义了“什么”和“什么时候”。那么切点就定义了“何处”。切点会匹配通知所要织入的一个或者多个链接点。
        2. 一般使用明确的类或者方法来指定这些切点。
        3. 做用:定义通知被应用的位置(在哪些链接点)
      4. 切面:
        1. 定义:切面是通知和切点的集合,通知和切点共同定义了切面的所有功能——它是什么,在什么时候何处完成其功能。
      5. 引入:
        1. 引入容许咱们向现有的类中添加方法或属性
      6. 织入:
        织入是将切面应用到目标对象来建立的代理对象过程。
        切面在指定的链接点被织入到目标对象中,在目标对象的生命周期中有多个点能够织入
        1. 编译期——切面在目标类编译时期被织入,这种方式须要特殊编译器。AspectJ的织入编译器就是以这种方式织入切面。
        2. 类加载期——切面在类加载到 JVM ,这种方式须要特殊的类加载器,他能够在目标类被引入应用以前加强该目标类的字节码。AspectJ5 的 LTW 就支持这种织入方式
        3. 运行期——切面在应用运行期间的某个时刻被织入。通常状况下,在织入切面时候,AOP 容器会为目标对象动态的建立代理对象。Spring AOP 就是以这种方式织入切面。

  3. Spring 对 AOP 的支持
    1. 并非全部的 AOP 框架都是同样的,他们在链接点模型上可能有强弱之分。
          有些容许对字段修饰符级别应用通知
          有些支持方法调用链接点
    2. Spring 提供的 4 种各具特点的 AOP 支持
      1. 基于代理的经典 AOP;
      2. @AspectJ 注解驱动的切面;
      3. 纯 POJO 切面;
      4. 注入式 AspectJ 切面;
    3. Spring 在运行期间通知对象
      1. 经过在代理类中织入包裹切面,Spring 在运行期间将切面织入到 Spring 管理的 Bean 中。

        代理类封装了目标类,并拦截被通知的方法调用,再将调用转发给真正的目标 Bean.
        当拦截到方法调用时,在调用目标 Bean 方法以前,代理会执行切面逻辑。
        当真正应用须要被代理的 Bean 时,Spring 才建立代理对象。若是使用 ApplicationContext,在 ApplicationContext 从 BeanFactory 中加载全部 Bean 时,Spring 建立代理对象,由于 Spring 在运行时候建立代理对象,因此咱们不须要特殊的编译器来织入 Spring AOP 的切面。
    4. Spring 支持方法建立链接点
      1. 由于 Spring 基于动态代理,因此 Spring 只支持方法链接点。
      2. Spring 缺失对字段链接点的支持,没法让咱们更加细粒度的通知,例如拦截对象字段的修改
      3. Spring 缺失对构造器链接点支持,我发在 Bean 建立时候进行通知。

  4. 使用切点选择链接点
    1. 切点用于准肯定位,肯定在什么地方应用切面通知。
    2. Spring 定义切点
      1. 在 Spring AOP 中,须要使用 AspectJ 的切点表达式来定义切点。
        AspectJ 指示器
        描述
        arg ()
        限制链接点的指定参数为指定类型的执行方法
        @args ()
        限制链接点匹配参数由指定注解标注的执行方法
        execution ()
        用于匹配链接点的执行方法
        this ()
        限制链接点匹配 AOP 代理的 Bean 引用为指定类型的类
        target ()
        限制链接点匹配特定的执行对象,这些对象对应的类要具有指定类型注解
        within()
        限制链接点匹配指定类型
        @within()
        限制链接点匹配指定注释所标注的类型(当使用 Spring AOP 时,方法定义在由指定的注解所标注的类里)
        限制匹配带有指定注释的链接点
                                         Spring 借助 AspectJ 的切点表达式语言来定义 Spring 切面
      2. 建立本身的切点

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

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

          还可使用非操做做为除了指定 ID 的 Bean 之外的其余 Bean应用通知

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

  5. 在 XML 中声明切面
    1. 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 : config>元素内
      <aop : declare-parents>
      为被通知的对象引入额外接口,并透明的实现
      <aop : pointcut>
      定义切点
相关文章
相关标签/搜索