AOP
简介
AOP(Aspect Oriented Progarmming)意为:面向切面编程,可以通过预编译的方式和运行期动态代理实现在不修改源代码的情况下给程序动态同一添加功能的一种技术。
AOP的编程思想就是把很多类对象重的横切问题点,从业务逻辑中分离出来,从而达到解耦的目的,增加代码的重用性,提高开发效率。
AOP的底层是基于动态代理实现的,动态代理包括JDK的动态代理(基于接口)和CGLIB的动态代理(基于继承)。
用途
日志记录 | 异常处理 |
权限验证 | 缓存处理 |
事务处理 | 数据持久化 |
效率检查 | 内容分发 |
核心概念
- aspect:切面,切面由切点和通知组成,即包括横切逻辑的定义也包括连接点的定义
- pointcut:切点,每个类都拥有多个连接点,可以理解是连接点的集合
- joinpoint:连接点,程序执行的某个特定位置,如某个方法调用前后等
- weaving:织入,将增强添加到目标类的具体连接点的过程
- advice:通知,是织入到目标类连接点上的一段代码,就是增强到什么地方?增强什么内容?
- target:目标对象,通知织入的目标类
- aop Proxy:代理对象,即增强后产生的对象
五种通知类型
- 前置通知(Before advice):在目标方法执行之前执行。它的执行条件是目标方法被调用之前。
- 后置通知(After advice):在目标方法执行之后执行。它的执行条件是目标方法的执行已经完成,无论是否发生异常。
- 返回通知(After-returning advice):在目标方法成功执行并返回结果后执行。它的执行条件是目标方法成功执行并且返回结果,没有抛出异常。
- 异常通知(After-throwing advice):在目标方法抛出异常后执行。它的执行条件是目标方法抛出了异常。
- 环绕通知(Around advice):在目标方法执行之前和之后都执行。它的执行条件是目标方法被调用。
历史
我们以日志为例:
传统的日志模式是在每一个需要打印日志的方法内写一遍日志方法,这样子会产生大量的重复代码。后来大家将重复的代码进行提炼,提炼成一个类,也就是公共类。之后再进行打印日志时只需要引入对应的logger类即可。
但是这样子仍存在一些问题:
- 很多类对象和Logger依然存在依赖关系,甚至每个类中的方法都需要调用Logger。
- 如果修改了方法,需要修改n遍,不能一次修改完成。
实现步骤
我们以增强日志显示为例
1.定义一个切面类Aspect
即在声明的类,添加@Compent和@Aspect两个注解,SpringBoot要引入spring-boot-stater-aop依赖包。
package com.ruoyi.lxy.controller;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAdvice {
private Logger logger = LoggerFactory.getLogger(MyAdvice.class);
}
2.定义切点Pointcut
定义切点,并定义切点在哪些地方执行,采用@Pointcut注解完成,例如@Pointcut(public*com.xxx.xxx.*.*(..))
规则:修饰符(可写可不写,但不能用*)+返回值类型+哪些包下的类+哪些方法+方法参数 "*" 代表不限,".." 两个点代表参数不限
//定义一个切面
@Pointcut(value = "execution(* com.ruoyi.lxy.controller.*.*(..))")
public void myPointcut(){
}
3.定义Advice通知
选择一个切点并利用五种通知类型注解来完成在某些切点的增强动作。
其中around与其他四种声明的参数不同,为ProceedingJoinPoint pip。
其中pip.proceed();是最重要的功能,它用于控制整个切入函数的执行。
//通知
public Object myLogger(ProceedingJoinPoint pip) throws Throwable{
//获取类名
String className = pip.getTarget().getClass().toString();
//获取方法名
String methodName = pip.getSignature().getName();
//获取参数数组
Object[] array = pip.getArgs();
ObjectMapper objectMapper = new ObjectMapper();
logger.info("执行调用前的操作");
Object proceed = pip.proceed();
logger.info("执行调用后的操作");
return proceed;
}
简单理解一下就是是定义一个切面类,类里面用切点来选择你要进行切入的类和方法,最后在通知里面选择一个切点来实现你要进行增强的功能。
标签:通知,切点,目标,pip,介绍,简单,SpringAOP,执行,方法 From: https://blog.csdn.net/qq_62188992/article/details/136681707