SpringBoot AOP 搭配注解的使用
自定义日志注解
创建自定义的日志注解,用于记录日志的操作,注解包含一个记录操作的枚举类
/**
* 记录操作日志注解
*
* @author zqf
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperateLog {
OperateTypeEnum operateType() default OperateTypeEnum.GET;
}
/**
* 操作类型枚举类
*
* @author zqf
*/
public enum OperateTypeEnum {
GET(0),
ADD(1),
DELETE(2),
UPDATE(3);
Integer value;
private OperateTypeEnum(Integer value) {
this.value = value;
}
public Integer getValue() {
return this.value;
}
}
AOP 面向切面编程
AOP 增强的实现
AOP 可以通过 5 个注解实现在不同的切面对方法进行增强
-
@Before
:在目标方法之前执行,可以通过JoinPoint
类获取目标方法的方法名以及参数 -
@After
:在目标方法之后执行,可以通过JoinPoint
类获取目标方法的方法名以及参数,即使目标方法出错产生异常也会执行该注解标注的方法逻辑 -
@AfterReturning
:当目标方法正常执行并返回时,执行该方法,若抛出异常则不执行该方法 -
@AfterThrowing
:当目标方法抛出异常时执行该方法,若目标方法正常执行则不会这姓该方法逻辑 -
@Round
:环绕方法,在目标方法执行的前后进行逻辑增强
AOP 基本使用
构造增强方法类,并标注注解@Aspect
表明这是一个切面容器,并使用Component
注入容器,在该类中,使用@Pointcut
注解标注切点
/**
* 操作日志 AOP
*
* @author zqf
*/
@Aspect
@Component
public class OperateLogAspect {
@Pointcut("@annotation(operateLog)")
public void operateLogPoint(OperateLog operateLog) {
}
/**
* 前置方法
*
* 在目标方法之前执行
*/
@Before(value = "operateLogPoint(operateLog)", argNames = "joinPoint,operateLog")
public void before(JoinPoint joinPoint, OperateLog operateLog) {
Object[] args = joinPoint.getArgs();
String methodName = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();
System.out.println("===== 执行前置方法 =====");
System.out.println("方法名>>>" + methodName);
System.out.println("参数>>>" + Arrays.asList(args).toString());
}
/**
* 后置方法
*
* 即使目标方法出错抛出异常也不影响执行
*/
@After(value = "operateLogPoint(operateLog)", argNames = "joinPoint,operateLog")
public void after(JoinPoint joinPoint, OperateLog operateLog) {
Object[] args = joinPoint.getArgs();
String methodName = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();
System.out.println("===== 执行后置方法 =====");
System.out.println("方法名>>>" + methodName);
System.out.println("参数>>>" + Arrays.asList(args).toString());
}
/**
* 环绕方法
*
* 只有调用 proceedingJoinPoint.proceed()方法才能够执行目标方法
*/
@Around(value = "operateLogPoint(operateLog)", argNames = "proceedingJoinPoint,operateLog")
public Object around(ProceedingJoinPoint proceedingJoinPoint, OperateLog operateLog) throws Throwable {
String methodName = proceedingJoinPoint.getTarget().getClass().getSimpleName() + "#" + proceedingJoinPoint.getSignature().getName();
String operateType = operateLog.operateType().name();
System.out.println("===== 执行环绕前方法 =====");
System.out.println("方法名>>>" + methodName);
System.out.println("执行操作>>>" + operateType);
// 目标方法的执行
Object proceed = proceedingJoinPoint.proceed();
System.out.println("===== 执行环绕后方法 =====");
System.out.println("方法名>>>" + methodName);
System.out.println("执行操作>>>" + operateType);
return proceed;
}
/**
* AfterReturning 方法
*
* 当方法正常执行返回时才执行该方法,若抛出异常则不会执行该方法
*/
@AfterReturning(value = "operateLogPoint(operateLog)", argNames = "joinPoint,operateLog")
public void afterReturning(JoinPoint joinPoint, OperateLog operateLog) {
Object[] args = joinPoint.getArgs();
String methodName = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();
System.out.println("===== 执行 AfterReturning 方法 =====");
System.out.println("方法名>>>" + methodName);
System.out.println("参数>>>" + Arrays.asList(args).toString());
}
/**
* AfterThrowing 方法
*
* 当方法抛出异常时执行该方法,弱方法正常执行则不执行该方法
*/
@AfterThrowing(value = "operateLogPoint(operateLog)", argNames = "joinPoint,operateLog")
public void afterThrowing(JoinPoint joinPoint, OperateLog operateLog) {
Object[] args = joinPoint.getArgs();
String methodName = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();
System.out.println("===== 执行 AfterThrowing 方法 =====");
System.out.println("方法名>>>" + methodName);
System.out.println("参数>>>" + Arrays.asList(args).toString());
}
}
编写控制类进行测试
/**
* AOP 测试 Controller
*
* @author zqf
*/
@RestController
@RequestMapping("/aop")
public class AopController {
@OperateLog(operateType = OperateTypeEnum.ADD)
@PostMapping("/add")
public String add() {
System.out.println("=====执行调用方法add()=====");
return "执行添加成功~";
}
@OperateLog(operateType = OperateTypeEnum.DELETE)
@DeleteMapping("/delete")
public String delete() {
System.out.println("=====执行调用方法delete()=====");
return "执行删除成功~";
}
@OperateLog(operateType = OperateTypeEnum.UPDATE)
@PutMapping("/update")
public String update() {
System.out.println("=====执行调用方法update()=====");
return "执行更新成功~";
}
@OperateLog(operateType = OperateTypeEnum.GET)
@GetMapping("/get")
public String get() {
System.out.println("=====执行调用方法get()=====");
// 测试 @AfterThrowing
throw new RuntimeException("测试 @AfterThrowing");
}
}
测试正常运行结果
测试运行异常结果