基于注解的方式,使用AOP切面实现日志记录功能
1. 什么是AOP
AOP称为面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为-可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。
常见的AOP使用场景:
- 记录操作日志
- 缓存处理
- Spring中内置的事务处理
2.AOP实现日志记录
2.1.导入依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
|
2.2.创建一个注解作为切点
新建一个注解,内部可以自定义一些属性
1 2 3 4 5 6 7 8 9 10 11 12
| import java.lang.annotation.*;
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LogAnnotation {
String operation() default "";
}
|
2.3.创建切面类
切面类中会定义通知和切点的关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import com.me.bibackend.annotation.LogAnnotation; 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 org.springframework.util.StopWatch; import java.lang.reflect.Method;
@Component @Aspect public class LogAspect {
@Pointcut("@annotation(com.me.bibackend.annotation.LogAnnotation)") public void pt() {}
@Around("pt()") public Object log(ProceedingJoinPoint joinPoint) throws Throwable { StopWatch stopWatch = new StopWatch(); stopWatch.start(); Object result = joinPoint.proceed(); stopWatch.stop(); System.out.println("方法耗时--"+stopWatch.getTotalTimeMillis()+"ms"); handleLog(joinPoint,result); return result; }
private void handleLog(ProceedingJoinPoint joinPoint, Object result) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); String operation = logAnnotation.operation(); String methodName = joinPoint.getSignature().getName(); String className = joinPoint.getTarget().getClass().getName(); Object[] args = joinPoint.getArgs(); String resultStr = result.toString(); System.out.println("方法名:"+methodName +",类名:"+className +",参数:"+args +",返回值:"+resultStr +",操作:"+operation); }
}
|
2.4.测试
1 2 3 4 5 6 7 8 9 10
| @RestController @RequestMapping("/test") public class TestController {
@GetMapping("/log") @LogAnnotation(operation = "测试") public String testLog() { return "test log"; } }
|
结果如下: