1、基本术语:
横切关注点:分布于应用中多处的功能被称为横切关注点,比如日志、安全、事务管理
切面:横切关注点可以被模块化为特殊的类,这些类被称为切面
通知:spring切面可以应用5种类型的通知
a.Before——在方法被调用之前调用通知
b.After——在方法完成之后调用通知,无论方法执行是否成功
c.After-returning——在方法成功执行之后调用通知
d.After-throwing——在方法抛出异常后调用通知
f.Around——通知包裹了被通知的方法,在被通知的方法调用之前和之后执行自定义的行为
连接点:这个点可以是调用方法时、抛出异常时、甚至修改一个字段时
切点:如果通知定义了切面的“什么”和“何时”,那么切点就定义了“何处”
切面:切面是通知和切点的结合,通知和切点共同定义了关于切面的全部内容——它是什么,在何时和何处完成其功能
引入:引入允许我们向现在有的类添加新方法或属性
织入:织入是将切面应用到目标对象来创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入
a.编译器——切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面 的。
b.类加载期——切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器,它可以在目标类被引入应用之前增强 该目标类的字节码。AspectJ5的LTW就支持以这种方式织入切面
c.运行期——切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代 理对象。spring aop就是以这种方式织入切面的。
2、spring提供了4种各具特色的aop支持:
a.基于代理的经典aop;
b.@AspectJ注解驱动的切面;
c.纯POJO切面
d.注入式AspectJ切面(适合spring各版本)
3、spring在运行期通知对象:通过在代理类中包裹切面,spring在运行期将切面织入到spring管理的bean中。
如图,代理类封装了目标类,并拦截被通知的方法的调用,再将调用转发给真正的目标Bean。
当拦截到方法调用时,在调用目标Bean,代理会执行切面逻辑。
直到应用需要被代理的Bean时,spring才创建代理对象。如果使用的是applicationcontext,在applicationcontext从BeanFactory中加载所有Bean时,spring创建被代理的对象(是代理对象还是被代理对象)。因为spring运行时才创建代理对象,所以我们不需要特殊的编译器来织入spring aop的切面
4、spring只支持方法连接点,因为spring基于动态代理
spring借助AspectJ的切点表达式语言来定义spring切面:
AspectJ指示器 | 描述 |
arg() | 限制连接点匹配参数为指定类型的执行方法 |
@args() | 限制连接点匹配参数由指定注解标注的执行方法 |
execution() | 用于匹配是连接点的执行方法 |
this() | 限制连接点匹配aop代理的Bean引用为指定类型的类 |
target() | 限制连接点匹配目标对象为指定类型的类 |
@target() | 限制连接点匹配特定的执行对象,这些对象对应的类要具备指定类型的注解 |
within() | 限制连接点匹配指定的类型 |
@within() | 限制连接点匹配指定注解所标注的类型(当使用spring aop时,方法定义在由指定的注解所标注的类里) |
@annotation | 限制匹配带有指定注解连接点 |
当使用其他指示器时,将会抛出IllegalArgumentException异常