一、基本术语
Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。指具体被增强的方法,即调用的方法
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。表达式中包含的方法统称为切入点。
Target(目标对象):织入 Advice 的目标对象.。
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
二、动态代理
1、jdk代理
JDK动态代理必须实现InvocationHandler接口,在此我称作handler类
使用代理对象,去增强类,具体的方法交给代理执行,执行方法前后需要的操作则交给handler类
例如:
执行方法时,不会直接进入方法,会先进入handler类,执行到invoke方法时才会进入方法,方法执行完后依旧会返回handler类,执行后续需要的操作
2、CGLIB动态代理
五大通知类型:
<1>前置通知 Before
目标方法执行之前的通知
<2>后置通知 After
在目标方法执行之后执行的通知,无论目标方法是否正常完成,都会执行
<3>最终通知(返回通知) AfterReturning
是在目标方法完整执行之后执行的通知。如果报异常是不会执行的
<4>异常通知 AfterThrowing
在目标方法抛出异常时执行的通知
<5>环绕通知 Around
在目标方法执行之前和之后都可以执行额外代码的通知。
在环绕通知中必须显式的调用目标方法,目标方法才会执行,这个显式调用时通过ProceedingJoinPoint来实现的,可以在环绕通知中接收一个此类型的形参,spring容器会自动将该对象传入,注意这个参数必须处在环绕通知的第一个形参位置。
具体注解方式如下:
执行顺序:
目标方法无异常
环绕前通知 >> 方法前通知 >> 目标方法(正常) >> 最终通知 >> 方法后通知 >> 环绕后通知
目标方法有异常
环绕前通知 >> 方法前通知 >> 目标方法(异常) >> 方法后通知
启用步骤:
用注解:
首先,在配置文件中,定义需要扫描的文件,其次在文件所包含的类加入注解,@Service等;其次,在配置文件中引用标签,就可以识别通知的注解定义一个切面类,用注解@Aspect ,然后指定切点:
注意:第一个*表示返回值为任意类型 第二个* 代表全部,括号里的..代表不管是否有参数;括号里没有..则只有执行无参时才会触发
1)直接载注解后面用value指定
2) 引用@Pointcut
然后,定义通知中的逻辑部分,最后执行即可。
用配置
同上,先指定扫描文件,再创建切面类对象
然后aop 标签内设置pointcut切点,aspect标签设置通知
注意:配置里五大通知方法的顺序影响程序里执行的先后顺序
@ Order()标签指定优先级,后面括号中的数字越小,优先级越高,越先执行