AOP技术及其Spring中的应用

一、AOP是什么

AOP(Aspect Oriented Programming)是面向切面编程,是一种设计思想,它要在不改变原有目标对象的基础上,为目标对象基于动态织入的特定方式(可以是编译是的动态,也可以运行时的动态)进行功能扩展.我们可以将设计思想理解为OOP(面向对象编程)思想的补充和完善,OOP强调的一种静态过程(一个项目由哪些子系统构成,一个子系统有哪些模块,一个模块又由哪些对象构成,一个对象又有哪些属性和方法).AOP是一个动态过程,它要为设计好的对象在动态编译或运行时做服务增益,例如,记录日志,事务增强,权限控制等。
 
其实就是要在不修改源代码的基础上对对象功能进行功能拓展。

二、AOP应用原理初步分析

有两种方式

1、借助JDK官方API为目标对象类型创建其兄弟类型对象,但是目标对象类型需要实现相应接口

2、借助CGLIB库为目标对象类型创建其子类类型对象,但是目标对象类型不能使用final修饰.

三、AOP相关术语

1、切面对象(Aspect)

封装了扩展业务逻辑的对象,在spring中可以使用@AspectJ描述

2、切入点(Pointcut)

定义了切入扩展业务逻辑的一些方法的集合(哪些方法运行时切入扩展业务),一般会通过表达式进行相关定义,一个切面中可以定义多个切入点的定义

3、连接点(JoinPoint)

切入点方法集合中封装了某个正在执行的目标方法信息的对象,可以通过此对象获取具体的目标方法信息,甚至去调用目标方法

4、通知(Advice)

切面(Aspect)内部封装扩展业务逻辑的具体方法对象,一个切面中可以有多个通知(例如@Around)

 

可以简单的将机场的一个安检口理解为连接点,多个安检口为切入点,安全检查过程看成是通知

四、Spring中关于Aop的注释

1、@Aspect

该注解描述的类型为切面对象类型,此切面中可以定义多个切入点和通知方法

2、@Pointcut

该注解用于定义切入点

3、@Around

该注解描述的方法,可以在切入点执行之前和之后进行业务拓展,在当前业务中

五、Spring切面对象定义

在springboot工程中,切面对象需要@Aspect

 1 package XXX;
 2 
 3 @Slf4j
 4 @Aspect
 5 @Component
 6 public class SysLogAspect {
 7     /**
 8      * bean("spring容器中bean的名字")这个表达式为切入点表达式定义的一种语法,
 9      * 它描述的是某个bean或多个bean中所有方法的集合为切入点,这个形式的切入点
10      * 表达式的缺陷是不能精确到具体方法的.
11      */
12      @Pointcut("bean(sysUserServiceImpl)")
13      public void doLog(){}//此方法只负责承载切入点的定义
14 
15     /**
16      * 此方法为日志通知方法
17      * @param joinPoint 连接点对象,此对象封装了要执行的切入点方法信息.可以通过连接点对象调用目标方法,这里的ProceedingJoinPoint类型只能应用于@Around描述的方法参数中
18      * @return 目标方法的执行结果
19      * @throws Throwable
20      */
21      @Around("doLog()")
22      public Object doAround(ProceedingJoinPoint jp)throws Throwable{
23          log.info("Start:{}",System.currentTimeMillis());
24          try {
25              Object result = jp.proceed();//执行目标方法(切点方法中的某个方法)
26              log.info("After:{}",System.currentTimeMillis());
27              return result;//目标业务方法的执行结果
28          }catch(Throwable e){
29              e.printStackTrace();
30              log.error("Exception:{}",System.currentTimeMillis());
31              throw e;
32          }
33      }
34 }
View Code

六、Spring切面工作原理分析

切面内部,切入点对应的目标业务方法执行时,底层会通过代理对象访问切面中的通知方法,进而通过通知方法为目标业务做功能增强.

JDK动态代理对象应用分析:

 其中:springboot工程默认的AOP代理为CGLIB代理,假如希望是JDK代理,则需要在springboot的配置文件中进行如下配置:

spring: 
   aop: 
     proxy-target-class: false

CGLIB动态代理对象应用分析:

七、Aop通知类型

Spring框架AOP模块定义通知类型,有如下几种:

1、@Around (所有通知中优先级最高的通知,可以在目标方法执行之前,之后灵活进行业务拓展.)

2、@Before (目标方法执行之前调用)

3、@AfterReturning (目标方法正常结束时执行)

4、@AfterThrowing (目标方法异常结束时执行)

5、@After (目标方法结束时执行,正常结束和异常结束它都会执行)

八、Aop切入点表达式

在Spring工程中对于切入点表达式,可以分成两大类型:

  • 粗粒度切入点表达式定义(不能精确到具体方法),例如bean,within表达式

  • 细粒度切入点表达式定义(可以精确到具体方法),例如execution,@annotation表达式

粗粒切入点表达式

1、bean(“bean的名字”) 表达式案例分析

1 1) bean(XxxServiceImpl),XxxServiceImpl类中所有方法集合为切入点
2 2) bean(*ServiceImpl),以ServiceImpl结尾的所有方法集合为切入点

2、within ("包名.类型") 表达式案例分析

1 1) within(XxxServiceImpl),XxxServiceImpl类中所有方法集合为切入点
2 2) within(Xxx.*),Xxx.service包下所有类中的方法集合为切入点
3 3) within(Xxx.service..*),Xxx.service包以及子包中所有类中方法的集合为切入点

细粒度切入点表达式

3、execution("返回值 类全名.方法名(参数列表)") 表达式案例分析

1 1) execution(int XxxService.validById(Integer,Integer))
2 2) execution(* Xxx.service..*.*(..))

4、@annotation(“注解的类全名”)表达式案例分析

1 1) @annotation(Xxx),由RequiredCache注解描述的方法为缓存切入点方法
2 2) @annotation(Xxx),由RequiredLog注解描述的方法为日志切入点方法

九、Aop切面优先级设置

当有多个切面时,并且对应着相同的切入点,假如切面中的通知方法的执行需要有严格顺序要求,此时我们需要设置切面的优先级。这个优先级可以通过@Order(数字优先级)注解进行描述,数字越小优先级越高。

设置日志切面优先级:

1 @Order(2)
2 @Aspect
3 @Component
4 public class XXX{}

设置缓存切面优先级:

1 @Order(1)
2 @Aspect
3 @Component
4 public class XXX{}

假如默认没有指定优先级,默认是最低的优先级。相同切入点下的多个切面会形成一个切面链。

原文地址:https://www.cnblogs.com/houyu/p/14278858.html