Spring 实战 六: 什么是面向切面编程 + Spring 对 aop 的支持 + 通过切点选择连接器

软件系统中的一些功能需要应用到应用程序的多个地方,如日志、安全、缓存和声明式事务。

散布于应用中多处的功能被称为横切关注点,这些横切关注点从逻辑上与应用的业务逻辑相分离,但往往会直接嵌入到业务逻辑之中,把这些横切关注点从业务逻辑分离正是面向切面编程要解决的问题。

  1. 继承委托使对象体系变得复杂,切面提供了另一种更加清晰简洁的方案。
  2. 每个关注点都集中在一个地方,不用分散在代码中。
  3. 服务模块更简洁,因为他们只关注核心功能。

什么是面向切面编程

通知(Advice)

切面要完成的工作(什么),何时完成这个工作(何时)。

  1. before:前置通知
  2. After:后置通知
  3. After-returning:目标方法执行之后执行通知
  4. After-throwing:在目标方法抛出异常后执行通知
  5. Around:包裹了目标方法,在方法执行前和调用后执行通知

连接点(Join point)

应用执行过程中能够插入切面的点,切面可以利用这些点插入到正常业务逻辑之中,并添加新的行为。

切点(Poincut)

一个切面不需要通知应用的所有连接点,切点有助于缩小切面所通知的连接点的范围(何处)。

切面(Aspect)

切面是通知和切点的结合,通知和切点共同定义了切面的全部内容——切面要完成什么功能,在何时何处完成。

引入(Introduction)

向现有类添加新的方法或属性。

织入(Weaving)

织入把切面应用到目标对象并创建新的代理对象,切面在指定的连接点织入到目标对象,可在多个可选的对象声明周期里织入:
1. 编译期:需要特殊的编译器,如 AspectJ 的织入编译器
2. 类加载期:目标类加载到 JVM 时织入,需要特殊的类加载器(ClassLoader),增强目标类的字节码
3. 运行期:运行时,AOP 容器动态的为目标对象创建代理对象,如 Spring AOP

Spring 对 aop 的支持

spring 提供了 4 种 aop 支持
1. 基于代理的经典 spring aop
2. 纯 POJO 切面(POJO:Plain ordinary java object - java beans)
3. @AspectJ 注解驱动的切面
4. 注入式 AspectJ 切面

spring aop 构建在动态代理之上,所有spring 对 aop 的支持局限于方法拦截。

spring 在运行时通知对象

  1. spring 代理封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的 bean,当代理拦截到方法调用时,在调用目标 bean 方法之前,会执行切面逻辑。
  2. spring运行时才创建代理对象,所以不需要特殊的编译器织入 spring aop 切面。

AspectJ 最初是以 java 语言扩展的方式实现的,有自己的编译器,除方法切点外,还提供了字段(拦截字段的修改)和构造器(构造器调用时)接入点。(JBoss 也提供了同样的粒度)

spring aop 与 AspectJ 项目

  1. spring aop 与 AspectJ 项目间有大量的协作,Spring 对 aop 的支持在很多方面借鉴了 AspectJ 项目(注解驱动、切点表达式语言的子集 …)
  2. spring 的 AspectJ 自动代理仅仅使用 @AspectJ 作为创建切面的指定,切面依然是基于代理的。这意味着尽管使用的是 @AspectJ 注解,我们还是限定于代理方法的调用,如果想利用 AspectJ 的所有能力,我们必须在运行时使用 AspectJ 并且不依赖 Spring 来创建基于代理的切面。

通过切点选择连接器

在 spring aop 中,要使用 AspectJ 的切点表达式语言来定义切点,spring 仅支持 AspectJ 切点指示器(pointcut designator)的一个子集。

AspectJ 指示器

  1. arg() 限制参数
  2. @args() 限制参数注解
  3. execution() 匹配连接点
  4. this() 限制代理的 bean 引用的类型
  5. target 限制目标对象类型
  6. @target() 限制目标对象类型,同时类型需要有特定注解
  7. within() 限制类型,包
  8. @within() …?
  9. annotation 限定注解
  10. bean() spring 提供的指示器,用于限定指定 bean

指示器使用

  1. “(..)” 表示不限定参数,”*” 任意返回值类型
  2. &&(and)、||(or)、!(not)
    Spring 实战 六: 什么是面向切面编程 + Spring 对 aop 的支持 + 通过切点选择连接器
    Spring 实战 六: 什么是面向切面编程 + Spring 对 aop 的支持 + 通过切点选择连接器