AOP概述

浮生长恨欢娱少,肯爱千金轻一笑。

Posted by MuZhou on January 8, 2018

AOP是什么

AOP全称aspect-oriented programming,与OOP是同一层级的概念,是一种编程范式,目的是通过横切关注点的分离来提高程序的模块化。这句话乍一看有点 不知所谓,仔细再看,其实AOP就是为了提升程序的模块化,分离横切关注点是它的手段。

什么叫横切关注点(Cross-cutting concern)呢?这个问题不太好回答。举个例子,在实际开发中,大家很可能会调用很多个RPC服务, 对于每个RPC服务的调用我们会关注它的耗时、入参和返回值,记录下日志以便分析问题。用传统的方式实现我们需要在每个RPC调用的地方记录数据并打印日志, 这样就会导致大量重复代码。在一个应用中,如果一个功能有很多地方要使用到,比如我们刚才说的记录日志,也比如 安全、事务管理、缓存等,而这些功能无法通过传统的设计或实现从系统中分离出来,这样的功能就叫做横切关注点。

那么横切关注点怎么分离,从哪里分离呢?AOP是将横切关注点从我们的核心业务逻辑中分离出来,而在了解怎么分离之前,我们先了解一下AOP的一些术语:

  • Aspect:切面,是AOP的模块化单位,类同于Class对OOP的意义。在Spring中,Aspect是一个标准的class,Spring提供两种机制将其定义为Aspect:
    1. 通过XML配置。

      <aop:config>
          <aop:aspect id="myAspect" ref="aBean">
              ...
          </aop:aspect>
      </aop:config>
      
      <bean id="aBean" class="...">
          ...
      </bean>
      
    2. 通过@Aspect注解。

      package org.xyz;
      import org.aspectj.lang.annotation.Aspect;
      
      @Aspect
      public class NotVeryUsefulAspect {
      
      }
      
  • Join point: 连接点,是程序执行中的特定的点,Aspect从这个点插入。可以作为Join Point的有:
    1. 字段:AspectJ和JBoss支持。
    2. 构造器:AspectJ和JBoss支持。
    3. 方法:AspectJ、JBoss、Spring都支持。
  • Advice:通知,是Aspect在Join Point上执行的动作,可以理解为Advice=要插入执行的代码 + 什么时候插入,即定义了Aspect的what和when。Spring支持以下五种Advice:
    1. Before
    2. After
    3. After-returning
    4. After-throwing
    5. Around
  • Pointcut:切入点,也就是Advice要插入的地方,即定义了Aspect的where。它与Join Point是一对一或一对多的关系,可以理解为Pointcut是Join Point的一个子集,Pointcut会定义一个规则,匹配上这个规则的Join Point(s) 的集合即为PointCut。Aspect=Advice + Pointcut。 Spring默认使用AspectJ的切点表达式语言来定义Pointcut。
  • Weaving:织入,是一个在特定Join Point将Aspect应用到目标对象,生成目标对象的代理对象的过程。Weaving一般发生在目标对象生命周期的以下几个时间点:
    1. Compile time:编译时,AspectJ支持这种方式,需要提供特殊的编译器。
    2. ClassLoad time:类加载时期,需要特定的类加载器(ClassLoader),AspectJ 5的LTW(load-time weaving)支持这种方式。
    3. Runtime:运行时,AOP容器动态生成一个代理对象来代理目标对象(动态代理技术),Spring目前使用这种方式。

参考资料:

  1. Aspect-oriented_programming
  2. Cross-cutting concern
  3. Aspect Oriented Programming with Spring
  4. 《Spring in Action, Third Edition》