简介
说明
本文介绍Spring(SpringBoot)的AOP的用法:自定义注解,在Controller的方法上使用此注解,然后在AOP中获得注解的相关信息。
本文使用@Around。
基础代码
项目结构、pom.xml、公共代码等与此文一样:Spring之AOP-将方法上的注解做为切点(用@Before) – 自学精灵
写法1:入参只有ProceedingJoinPoint
@Around入参只写ProceedingJoinPoint,有返回值。这个返回值会作为Controller数据返回回去。
AOP代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.common.util.JsonUtil;
import com.example.demo.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* Around结合方法注解获得操作日志
*/
@Aspect
@Component
public class OperationLogAspectByAround {
// 切点表达式,表示加了OperationLog注解的都是切点,路径是自定义注解的全路径
@Pointcut("@annotation(com.example.demo.annotation.OperationLog)")
//多个切点时可指定优先级
// @Order(1)
public void pointcut() {
}
//有ProceedingJoinPoint无注解类,有返回值
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("################## around 进入 ##################");
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
System.out.println("--------------------- 方法信息 ---------------------");
System.out.println("joinPoint.getTarget().toString() : " + joinPoint.getTarget().toString());
System.out.println("methodSignature.getName() : " + methodSignature.getName());
System.out.println("method.getName() : " + method.getName());
System.out.println("method.getReturnType().getName() : " + method.getReturnType().getName());
System.out.println("--------------------- 入参数据 ---------------------");
Object[] objects = joinPoint.getArgs();
System.out.println(JsonUtil.toJson(objects));
System.out.println("--------------------- 真正执行 ---------------------");
Object object = joinPoint.proceed();
System.out.println("--------------------- 执行结果 ---------------------");
System.out.println(JsonUtil.toJson(object));
System.out.println("--------------------- 注解数据 ---------------------");
OperationLog operationLog = method.getAnnotation(OperationLog.class);
System.out.print("type: " + operationLog.type());
System.out.println("\tdesc: " + operationLog.desc());
return object;
}
}
测试
1.测试添加接口

后端结果
################## around 进入 ##################
--------------------- 方法信息 ---------------------
joinPoint.getTarget().toString() : com.example.demo.controller.UserController@3bfbf09e
methodSignature.getName() : testAdd
method.getName() : testAdd
method.getReturnType().getName() : com.example.demo.entity.User
--------------------- 入参数据 ---------------------
[{"id":12,"userName":"Tony","note":"abc"}]
--------------------- 真正执行 ---------------------
--------------------- 执行结果 ---------------------
{"id":12,"userName":"Tony","note":"abc"}
--------------------- 注解数据 ---------------------
type: 添加 desc: 添加数据
2.测试修改接口

后端结果
################## around 进入 ##################
--------------------- 方法信息 ---------------------
joinPoint.getTarget().toString() : com.example.demo.controller.UserController@3bfbf09e
methodSignature.getName() : testUpdate
method.getName() : testUpdate
method.getReturnType().getName() : com.example.demo.entity.User
--------------------- 入参数据 ---------------------
[{"id":11,"userName":"Peter","note":"hello"}]
--------------------- 真正执行 ---------------------
id = 11 userName = Peter note = hello
--------------------- 执行结果 ---------------------
{"id":11,"userName":"Peter","note":"hello"}
--------------------- 注解数据 ---------------------
type: 更新 desc: 更新数据
写法2:入参为ProceedingJoinPoint + 注解类
@Around入参为ProceedingJoinPoint + 注解类,有返回值。这样就不用写@PointCut了,返回值会作为Controller数据返回回去。
AOP代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.common.util.JsonUtil;
import com.example.demo.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* Around结合方法注解获得操作日志
*/
@Aspect
@Component
public class OperationLogAspectByAround {
// 有ProceedingJoinPoint和注解类,有返回值。这样就不用写@Pointcut了
@Around("@annotation(operationLog)")
public Object around(ProceedingJoinPoint joinPoint, OperationLog operationLog) throws Throwable {
System.out.println("################## around 进入 ##################");
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
System.out.println("--------------------- 方法信息 ---------------------");
System.out.println("joinPoint.getTarget().toString() : " + joinPoint.getTarget().toString());
System.out.println("methodSignature.getName() : " + methodSignature.getName());
System.out.println("method.getName() : " + method.getName());
System.out.println("method.getReturnType().getName() : " + method.getReturnType().getName());
System.out.println("--------------------- 入参数据 ---------------------");
Object[] objects = joinPoint.getArgs();
System.out.println(JsonUtil.toJson(objects));
System.out.println("--------------------- 真正执行 ---------------------");
Object object = joinPoint.proceed();
System.out.println("--------------------- 执行结果 ---------------------");
System.out.println(JsonUtil.toJson(object));
System.out.println("--------------------- 注解数据 ---------------------");
System.out.print("type: " + operationLog.type());
System.out.println("\tdesc: " + operationLog.desc());
return object;
}
}
测试
1. 测试添加接口

后端结果
################## around 进入 ##################
--------------------- 方法信息 ---------------------
joinPoint.getTarget().toString() : com.example.demo.controller.UserController@19e107d7
methodSignature.getName() : testAdd
method.getName() : testAdd
method.getReturnType().getName() : com.example.demo.entity.User
--------------------- 入参数据 ---------------------
[{"id":11,"userName":"Tony","note":"cccc"}]
--------------------- 真正执行 ---------------------
--------------------- 执行结果 ---------------------
{"id":11,"userName":"Tony","note":"cccc"}
--------------------- 注解数据 ---------------------
type: 添加 desc: 添加数据
测试2:测试修改接口

后端结果
################## around 进入 ##################
--------------------- 方法信息 ---------------------
joinPoint.getTarget().toString() : com.example.demo.controller.UserController@19e107d7
methodSignature.getName() : testUpdate
method.getName() : testUpdate
method.getReturnType().getName() : com.example.demo.entity.User
--------------------- 入参数据 ---------------------
[{"id":32,"userName":"Peter","note":"hi"}]
--------------------- 真正执行 ---------------------
id = 32 userName = Peter note = hi
--------------------- 执行结果 ---------------------
{"id":32,"userName":"Peter","note":"hi"}
--------------------- 注解数据 ---------------------
type: 更新 desc: 更新数据

请先 !