普通的MVC架构,Controller层是api的入口,现在想对每一个api的入参和返回值打印日志,用aspect 来实现很是方便。
本文侧重实践,概念层面就不在陈述了。
第一步:自定义一个打印日志的注解
/** * 自定义打印日志的注解 * */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ServiceLog { }
这里对@Retention 和 @Target做一下说明。
@Retention属于元注解(元注解的作用就是负责注解其他注解,有@Retention/@Target/@Documented/@Inherited),
@Retention用于定于注解的生命周期,即在什么时期时期生效,有如下三个值:
1、RetentionPolicy.SOURCE:存在源码级,编译时就会被忽略
2、RetentionPolicy.CLASS:存在于编译期,即class中会有
3、RetentionPolicy.RUNTIME:在jvm运用时存在,能被读取到和使用
@Target是注解用在什么地方,是某个包、还是类、方法、构造器等等
ElemenetType.METHOD:方法
ElemenetType.PACKAGE :包
ElemenetType.PARAMETER :参数
等等
第二步:新增一个切面类,里面提供切入点方法和调用切点方法时机的方法
@Aspect @Component public class WebLogAscept { /** * 以自定义 @WebLog 注解为切点 */ // @Pointcut("@annotation(com.tm.backend.newapproval.aspect.WebLog)") // 扫描有WebLog注解的方法 @Pointcut("execution(* com.tm.backend.approval.endpoint.*.*(..))") // 扫描包下所有方法 public void webLog() { } /** * 切点之前 */ @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 开始打印请求日志 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); System.out.println("方法名:"+signature.getName()+". 入参:"+joinPoint.getArgs()); } /** * 环绕 */ @Around("webLog()") public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { Object result = proceedingJoinPoint.proceed(); System.out.println("返回值:"+result); return result; } }
总结:重点是自定义注解并且添加了切点后,这些切点在方法的什么地方用,并且获取相应的属性