Spring in Action --- 第四章 面向切面的Spring

什么是面向切面编程

以马士兵老师最简单的话来说,你有一个查询的请求,查询的过程是一条线,在这条线的头和尾咔嚓切两刀,然后往里面拼入两条新的线,这就是面向切面编程.

具体一点来说,有一些功能是大部分方法都需要的,比如安全性,事务,但是又不希望在许多地方重复的造轮子.你可能会想到用代理,或者将这些方法抽取为一个类后引用,但是仔细想一想,这真的合适吗?比如一个查询的操作,关心的可能只是能不能查到数据,而不会去关心安全性,因为这并不是查询操作所要做的事情.在这种情况下,面向切面编程就能帮上很大的忙

定义AOP术语

在使用面向切面编程(AOP)之前,我们先来了解一下AOP的专有名词

通知

通知定义了且面试什么以及何时使用,Spring 切面可以应用5种类型的通知:

  • 前置通知(Before):在目标方法被调用之前调用通知功能
  • 后置通知(After):在目标方完成之后调用通知,不关心方法的输出是什么
  • 返回通知(After-Return):在目标方法成功执行后调用通知
  • 异常通知(After-Throwing):在目标方法抛出异常后调用通知
  • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为

连接点

连接点是在应用执行过程中能够插入切面的一个点,切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为

切点

如果是通知定义了切面的"什么"和"何时"的话,那么切点就定义了"何处",我们定义在何处需要这些切面代码

切面

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

引入

引入允许我们向现有的类添加新方法或属性.

织入

织入是把切面应用到目标对象并创建新的代理对象的过程,在目标对象的生命周期里有多个点可以进行织入:

  • 编译期 --- 切面在目标类编译时被织入,AspectJ的织入编译器就是一这种方式织入切面的
  • 类加载期 --- 切面在目标类加载到JVM时被织入
  • 运行期 --- 切面在应用运行时的某个时刻被织入

Spring对AOP的支持

Sping提供了4中类型的AOP支持:

  • 基于代理的经典Spring AOP
  • 纯POJO切面
  • @AspectJ 注解驱动的切面
  • 注入式AspectJ切面

Spring AOP构建在动态代理基础之上,因此,Spring 对 AOP的支持局限于方法拦截

Spring通知是Java编写的

Spring所创建的通知全都是用标准的Java类编写的,这样的话,我们可以方便的开发切面,但是AspectJ与之相反,它是通过Java语言扩展的方式实现的,通过特有的AOP语言,我们可以获得更强大和细粒度的控制,但是需要学习额外的工具和语法

Spring在运行时通知对象

通过在代理类中包裹切面,Spring在运行期把切面植入到Spring管理的bean中.直到应用需要被代理的bean时,Spring才创建代理对象

Spring只支持方法级别的连接点

因为Spring基于动态代理,所以只支持方法连接点.

通过切点来选择连接点

在Spring AOP中,要使用 AspectJ的其诶单表达式语言来定义切点.关于Spring AOP的AspectJ切点,最重要的一点就是Spring仅支持AspectJ切点指示器的一个子集,下表列出了Spring AOP所支持的AspectJ切点指示器:

AspectJ 指示器 描 述
arg() 限制连接点匹配参数为指定类型的执行方法
@args() 限制连接点匹配参数有指定注解标注的执行方法
execution() 用于匹配是连接点的执行方法
this() 限制连接点匹配AOP代理的bean引用为指定类型的类
target() 限制连接点匹配目标对象为指定类型的类
@target() 限制连接点匹配特定的执行对象,这些对象对应的类要具有指定类型的注解
within() 限制连接点匹配指定的类型
@within() 限制连接点匹配指定注解所标注的类型(当使用 Spring AOP 时,方法定义在由指定的注解所标注的类里)
@annotation 限制匹配带有指定注解的连接点

注意以上指示器中只有execution指示器是实际执行匹配的,其他的指示器都是用来限制匹配的

编写切点

下面是一个简单的示例:

execution(* concert.Performance.perform(..)

第一个星号表示返回任意类型,后面表示使用任意参数的指定某个类的某一个方法.如果希望匹配指定包下所有的方法,可以这么写:

execution(* com.**.*(..))

表示com包及其子包下任何类的使用任何参数的任何方法都会被匹配到.

现在我们假设需要配置的切点仅匹配concert包,可以使用within()指示器来限制匹配:

execution(* concert.Performance.perform(..) && within(concert.*)

在切点中选择bean

Spring引入了一个新的指示器:bean(),它允许我们在切点表达式中使用bean的ID来标识bean,bean()使用beanID或bean名称作为参数来限制切点只匹配特定的bean

posted @ 2017-01-18 16:20  吹哔战将  阅读(287)  评论(0编辑  收藏  举报