AOP切面讲解<一>

117 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

Spring AOP通过JDK或者CGLIB动态代理创建指定方法的代理,执行方法时则根据切点匹配到对应的增强,做相应的处理。

一、AOP的相关术语

1.通知(Advice):
通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。
2.连接点(Joinpoint):
程序能够应用通知的一 个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。
3.切入点(Pointcut)
通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,spring中允许我们方便的用正则表达式来指定
4.切面(Aspect)
通知和切入点共同组成了切面:时间、地点和要发生的“故事”
5.引入(Introduction)
引入允许我们向现有的类添加新的方法和属性(spring提供了一个方法注入的功能)
6.目标(Target)
即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做的事)
7.代理(proxy)
应用通知的对象,详细内容参见设计模式里面的代理模式
8.织入(Weaving)
把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:
(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器

(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码

(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

二、Spring提供了4种实现AOP的方式

1、经典的基于代理的AOP
2、@AspectJ注解驱动的切面
3、纯POJO切面通过(aop:fonfig标签配置)

4、注入式AspectJ切面

基于代理的AOP Spring支持五种类型的通知:

  • Before(前):org.apringframework.aop.MethodBeforeAdvice
  • After-returning(返回后):org.springframework.aop.AfterReturningAdvice
  • After-throwing(抛出后):org.springframework.aop.ThrowsAdvice
  • Arround(周围):org.aopaliance.intercept.MethodInterceptor
  • Introduction(引入):org.springframework.aop.IntroductionInterceptor

注解驱动的切面:

  • @Before(EDP):前置输出
  • @AfterReturning(value=EDP,returning="result"):后置通知(通过returning属性 可以定义方法返回值,作为参数)
  • @AfterThrowing(value=EDP,throwing="ex"):异常通知(通过设置throwing属性,可以设置发生异常对象参数)
  • @After(value=EDP):最终通知
  • @Around(EDP):环绕通知(around方法的返回值就是目标代理方法执行返回值,参数为ProceedingJoinPoint 可以调用拦截目标方法执行)

三、切点(Pointcut)切入方式

1、方法切点

  • execution,作用方法,最常用。指定方法返回类型,类名,方法名,参数名等与方法相关的部件。
  • @annotation,作用方法。方法注解类名

2、目标类切点

  • within,作用目标类。指定全路径类名。
  • target,作用目标类。指定类名。
  • @within,作用目标类。类型注解类名。
  • @target,作用目标类。类型注解类名。

3、方法入参切点

  • args,作用参数。指定全路径的类名。
  • @args,作用参数。类型注解类名。

4、代理类切点

  • this,作用代理类。类名。

四、多个切面同切优先级

AOP的实现对于一个切面中多个不同Advice的执行顺序,是由对应增强器的invoke方法本身实现的,具体顺序如下所示:

1、目标方法正常执行:@Around前 ->@Before ->执行方法 ->  @Around后 -> @After -> @AfterReturning

2、目标方法抛异常:@Around前 ->@Before ->方法报错 -> @After -> @AfterThrowing

对于多个切面类切同一个方法,哪个切面类中的增强器先执行,AOP中没有规定不同切面的执行顺序,都是把切面打乱放进了List中,但从放入List中的顺序追溯,可知对应的是Spring加载类后注册BeanDefinition的顺序,即Spring注册BeanDefinition的顺序。而此顺序有两个方法控制,一个是在类上加@Order(123)注解,后面的数字越小越早加载;另一个是实现Ordered接口,重写getOrder方法,返回的值越小越早加载。