1. 导入AOP的包
<!-- aop aspect注解导包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
2. springMVC的配置
<!--扫描,Controller类-->
<context:component-scan base-package="com.JXWork"/>
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true">
<!-- 指定@Aspect类,支持正则表达式,符合该表达式的切面类才会被应用-->
<aop:include name="annotationLogAspect"></aop:include>
</aop:aspectj-autoproxy>
<bean id="annotationLogAspect" class="com.JXWork.service.AopLog.AnnotationLogAspect"/>
3. 定义AnnotationLog注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})//表示只能给类添加该注解
@Retention(RetentionPolicy.RUNTIME)//这个必须要将注解保留在运行时
public @interface AnnotationLog {
String name() default "";
}
4. 声明切面类
定义切点(PointCut),定义连接点(JoinPoint),在这个AnnotationLog注解标注的方法上加入日志切入点。
package com.train.annotation;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @auther: TF12778 2022/8/25 10:36
* @description:
*/
@Component
@Slf4j
@Aspect
public class LogAspect {
@Pointcut("@annotation(com.train.annotation.AnnotationLog)")
public void logPoint() {
}
@Before("logPoint()")
public void doBefore(JoinPoint joinPoint) {
}
@After("logPoint()")
public void doAfter(JoinPoint joinPoint) {
}
/**
* ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中,
* 添加了 Object proceed() throws Throwable //执行目标方法
* Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法
*/
@Around("logPoint()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
//获取连接点的方法签名对象
Signature signature = joinPoint.getSignature();
if (!(signature instanceof MethodSignature)) {
throw new IllegalArgumentException("该注解只能用于方法");
}
MethodSignature methodSignature = null;
methodSignature = (MethodSignature) signature;
// 获取连接点所在的目标对象类
Class target = joinPoint.getTarget().getClass();
Method method = target.getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
AnnotationLog annotationLog = method.getAnnotation(AnnotationLog.class);
log.info("注解内容获取:" + annotationLog.name());
// 获取连接点方法运行时的入参列表
Object[] params = joinPoint.getArgs();
Map<String, Object> paramMap = object2Map(params[0]); // 参数转换为map
log.info("{}.{}方法请求入参:{}", target.getSimpleName(), method.getName(), JSON.toJSONString(paramMap));
Object result = joinPoint.proceed();
log.info("{}.{}方法执行结果:{}", target.getSimpleName(), method.getName(), JSON.toJSONString(result));
return result;
}
/**
* 实体对象转成Map
* @param obj 实体对象
* @return
*/
public static Map<String, Object> object2Map(Object obj) {
Map<String, Object> map = new HashMap<>();
List<Field> fieldList = new ArrayList<>() ;
if (obj == null) {
return map;
}
Class clazz = obj.getClass();
while (clazz != null) {
fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
clazz = clazz.getSuperclass();
}
try {
for (Field field : fieldList) {
field.setAccessible(true);
if (Objects.equals("serialVersionUID", field.getName()) ) {
continue;
}
map.put(field.getName(), field.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
}
5. 在具体方法上加入注解 @AnnotationLog
@RequestMapping(value = "/selectCustomerList")
@AnnotationLog(name = "打印执行结果")
public List<jxzCustomer> selectCustomerList(jxzCustomer query) {
List<jxzCustomer> list = customerService.selectList(query);
return list;
}
测试结果: