Java AOP切面日志处理

1,引入依赖


  <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>
   

2,配置日志切面

@Aspect
@Component
@Slf4j
@Order(1)
public class LogOperationAop {

//定义了一个切入点
    @Pointcut("@annotation(com.XX.XX.annotion.OpLog)")
    public void methodAspect() {
    }
    
//定义了一个前置通知,这个通知对刚刚上面我们定义的切入点中的所有方法有效
    @Before("methodAspect()")
    public void doAudit(JoinPoint joinPoint) throws NoSuchMethodException {
    //目标对象
        Class<?> clazz = joinPoint.getTarget().getClass();
    //方法签名
        String method = joinPoint.getSignature().getName();
	//方法参数
		Object[] thisArgs = joinPoint.getArgs();
    //参数类型
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
    //方法
        Method thisMethod = clazz.getMethod(method, parameterTypes);
    //自定义日志接口,检查指定的对象引用不为空
   		OpLog methodAnnotation = Objects.requireNonNull(AnnotationUtils.findAnnotation(thisMethod, OpLog.class));
        AuditModuleEnum module = methodAnnotation.module();
        String format = methodAnnotation.format();
    //与模板参数的值比对
        Object[] spEls = SpElUtil.spElEval(methodAnnotation.spElArgs(), thisArgs);
        String summary = MessageFormatter.arrayFormat(format, spEls).getMessage();
        String detail = null;
        if (thisArgs.length > 0) {
            detail = objectMapper.writeValueAsString(thisArgs[0]);
        }
     //将日志保存进数据库
        service.recordLog(module, summary, detail);
       
    }


    @Before("methodAspect()")
    public void doAudit(JoinPoint joinPoint) throws NoSuchMethodException {
        System.out.println("Beforeadvice");
    }

    @After(value = "methodAspect()")
    public void after() {
        System.out.println("After advice");
    }

    @AfterReturning(value = "methodAspect()")
    public void afterReturning() {
        System.out.println("AfterReturning advice");
    }

    @AfterThrowing(value = "methodAspect()")
    public void afterThrowing() {
        System.out.println("AfterThrowing advice");
    }
  
    @Around("methodAspect()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("环绕通知开始");
        System.out.println("目标对象 = " + proceedingJoinPoint.getTarget());
        System.out.println("方法签名 = " + proceedingJoinPoint.getSignature());
        System.out.println("方法参数 = " + proceedingJoinPoint.getArgs());
        Object proceed=proceedingJoinPoint.proceed();//放行
        System.out.println( "目标方法执行完毕");
        return proceed;
    }

}

注意:
1,前置和后置通知的方法参数都是 JoinPoint
2,环绕通知的方法参数是 ProceedingJoinPoint

3,匹配当前执行方法持有指定注解

//自定义aop生效注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) //指定运行时生效
public @interface OpLog {
    
    AuditModuleEnum module() default AuditModuleEnum.UNKNOWN;

    String format() default "";

    String [] spElArgs() default "";
}

业务层:


//使用切面注解
  @ApiOperation(value = "新增")
  @RequestMapping(path = "/add", method = RequestMethod.POST)
  @OpLog(module = AuditModuleEnum.METADATA, format = "新增,{}", spElArgs = {"[0].toString()"})
  public void add(@Valid @RequestBody param param) {
      service.add(param);
  }
    

4,注解

类注解:

@Aspect 将一个类定义为一个切面类
@Component 申明是个spring管理的bean
@order(i) 标记切面类的处理优先级,i值越小,优先级别越高.PS:可以注解类,也能注解到方法上

方法注解:

@Pointcut定义一个方法为切点里面的内容为一个表达式,下面详细介绍
@Before 在切点前执行方法,内容为指定的切点
@After 在切点后,return前执行,
@AfterReturning在切入点,return后执行,如果想对某些方法的返回参数进行处理,可以在这操作
@Around 环绕切点,在进入切点前,跟切点后执行
@AfterThrowing 在切点后抛出异常进行处理
@order(i) 标记切点的优先级,i越小,优先级越高

@Pointcut("execution( com.javacode2018.aop.demo9.test1.Service1.*(…))")*

表达式标签(10种)

execution:用于匹配方法执行的连接点
within:用于匹配指定类型内的方法执行
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也* 类型匹配
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法

@within:用于匹配所以持有指定注解类型内的方法
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行
@annotation:用于匹配当前执行方法持有指定注解的方法

5,更多优秀文章:

https://zhuanlan.zhihu.com/p/153317556

https://blog.csdn.net/qq_36826506/article/details/81436819

https://blog.csdn.net/qq_35206261/article/details/81945618?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-5.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-5.no_search_link

https://blog.csdn.net/q982151756/article/details/80513340

https://cloud.tencent.com/developer/article/1584491

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值