一、面向对象编程 - AOP
AOP(Aspect Oriented Programming)最早是AOP联盟的组织提出的,指定的一套规范。
二、Spring AOP 和 AspectJ 之间的区别
AspectJ是一个java实现的AOP框架,是目前实现AOP框架中最成熟,功能最丰富的语言。
AspectJ的织入方式是静态织入,在编译期,使用特殊的编译器(ajc编译器)把aspect类编译成class字节码后,在java目标类编译时织入,即先编译aspect类再编译目标类。
Spring AOP最初是使用xml配置的方式实现AOP。Spring 2.0使用了和AspectJ 5一样的注解,并通过解析 AspectJ 风格的切点表达式来确定连接点。但是,运行时仍旧是纯的Spring AOP,并不依赖于AspectJ的编译器或者织入器。
Spring AOP的织入方式是动态织入,在运行时动态的将要增强的代码织入到目标类中,使用动态代理技术实现:JDK动态代理(Proxy,底层通过反射实现);CGLIB动态代理(底层通过继承实现)。
Spring AOP更易用,AspectJ更强大。Spring AOP 只支持方法级别的连接点,而且只能使用简单的切点表达式。AspectJ支持更多的连接点类型,如构造器、属性、静态初始化器等,而且具有更强大的切点表达式语言。
三、切入点(pointcut)的申明规则
- execution:根据方法的执行情况匹配切入点。
- args:根据方法参数匹配切入点。
- within:根据类名匹配切入点。
- target:根据目标对象的类型匹配切入点。
- this:根据代理对象的类型匹配切入点。
- @annotation:根据方法是否有指定的注解匹配切入点。
- @args:根据方法参数是否有指定的注解匹配切入点。
- @within:根据类是否有指定的注解匹配切入点。
- @target:根据目标对象是否有指定的注解匹配切入点。
目标对象和代理对象的区别:
代理对象包含了切面所定义的增强逻辑以及目标对象的原始业务逻辑。因此,当我们调用代理对象的方法时,实际上会触发切面的增强逻辑,然后再调用目标对象的原始业务逻辑。
如果目标对象实现了至少一个接口,则 Spring 将使用 JDK 动态代理。通过实现这些接口来创建代理对象。
如果目标对象没有实现任何接口,则 Spring 将使用 CGLIB 动态代理,通过创建目标对象的子类来创建代理对象。
四、通知类型
- Before:在连接点执行前执行通知。
- After Returning:在连接点成功执行后执行通知。
- After Throwing:在连接点抛出异常后执行通知。
- After:在连接点结束时(无论正常或异常)执行通知。
- Around:在连接点之前和之后,包裹着连接点执行通知。
执行顺序:
如果有多个切面,可以在切面上使用@Order
注解,指定优先级,优先级值越低,越先执行。
@Aspect
@Order(1)
public class MyAspect {
// ...
}