1.自定义一个注解
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoLog {
}
2.定义一个切面类
@Slf4j
@Aspect
@Component
public class AutoLogAspect {
/**
* 定义切点表达式 匹配带有@AutoLog注解的方法或者带有@AutoLog注解的类
*/
@Pointcut("@annotation(my.zyj.annotation.AutoLog)||@within(my.zyj.annotation.AutoLog)")
public void pointCut() {
}
/**
* 定义一个环绕通知方法,在指定切点周围执行
*/
@Around("pointCut()")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
// 拼接获取类名方法名
String method = joinPoint.getSignature().getDeclaringType().getSimpleName() + "." + joinPoint.getSignature().getName();
// 获取方法参数
Object[] args = joinPoint.getArgs();
StringBuilder str = new StringBuilder();
try {
//拼接信息
Arrays.stream(args).filter(Objects::nonNull).forEach(e -> str.append(e.getClass().getSimpleName()).append(":").append(JsonUtil.toJsonString(e)).append("; "));
} catch (Exception e) {
//防止异常情况导致参数解析失败而阻塞链路
log.warn("autoLog fail to print args ,cause by", e);
}
// 方法开始时间
Date startTime = new Date();
log.info("[{}] start --------------->> {}", method, str);
// 执行方法
Object result = joinPoint.proceed();
// 方法结束时间
Date endTime = new Date();
log.info("[{}] end. cost time:{}s <<---------------", method,(endTime.getTime() - startTime.getTime())/1000);
return result;
}
}
3. 测试
@RestController
@RequestMapping("/test")
public class MyTestController {
@GetMapping("/test")
@AutoLog
public void test(@Param("str") String str, @Param("name") String name){
AtomicInteger atomicInteger = new AtomicInteger();
for (int i = 0; i <= 100; i++) {
atomicInteger.addAndGet(i);
}
System.out.println("0到100的和为: "+atomicInteger.get());
}
}
4. 结果
2023-07-11 17:46:20.900 INFO 7336 --- [nio-8081-exec-2] my.zyj.annotation.AutoLogAspect : [MyTestController.test] start --------------->> String:"測試str"; String:"測試name";
0到100的和为: 5050
2023-07-11 17:46:20.922 INFO 7336 --- [nio-8081-exec-2] my.zyj.annotation.AutoLogAspect : [MyTestController.test] end. cost time:0s <<---------------