zoukankan      html  css  js  c++  java
  • 记录一次SpringBoot实现AOP编程

    需求

      最近碰到一个问题,需要对关键操作的入参和返回值进行记录,并不是使用log记录,而是插入到数据库中。

      思路:如果采用硬编码,在每个操作后都添加,会产生大量重复代码。因而打算使用自定义注解,通过AOP对注解进行拦截,对有注解的方法进行拦截,下面给出自己Demo的实现。

    实现

      第一步:导入Maven依赖。

    1         <dependency>
    2             <groupId>org.springframework.boot</groupId>
    3             <artifactId>spring-boot-starter-aop</artifactId>
    4         </dependency>

      第二步:自定义注解,定义注解的属性。

     1 @Target({ElementType.METHOD, ElementType.TYPE})
     2 @Retention(RetentionPolicy.RUNTIME)
     3 public @interface RecordRpc {
     4     // 具体路径
     5     String url();
     6     // 数据来源
     7     String dataSource();
     8     // 备注
     9     String remarks();
    10 }

      第三步:定义对注解拦截后的具体操作

     1 @Aspect
     2 @Component
     3 public class RecordAnnotationAop {
     4 
     5     @Autowired
     6     PostService postService;
     7 
     8     // 声明拦截的注解
     9     @Pointcut("@annotation(ticket.annotation.RecordRpc)")
    10     private void cutMethod() {
    11 
    12     }
    13 
    14     // 使用环绕通知,对目标方法进行拦截
    15     @Around("cutMethod()")
    16     public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    17 
    18 
    19         // 执行拦截的方法
    20         Object proceed = joinPoint.proceed();
    21 
    22         // 获取目标方法的名称
    23         String methodName = joinPoint.getSignature().getName();
    24         // 获取方法传入参数
    25         Object[] params = joinPoint.getArgs();
    26         JSONObject obj = new JSONObject();
    27         if (params.length > 0) {
    28             for (int i = 0; i < params.length; i++) {
    29                 obj.put("arg[" + i + "]", params[i]);
    30             }
    31         }
    32         System.out.println("AOP入参:" + methodName + obj.toJSONString());
    33 
    34         // 获取执行结果
    35         System.out.println("AOP执行结果:");
    36         if (proceed != null) {
    37             System.out.println(JSON.toJSON(proceed));
    38         }
    39         // 获取注解上参数
    40         System.out.println("注解上参数:");
    41         RecordRpc annotation = getDeclaredAnnotation(joinPoint);
    42         System.out.println("url:" + annotation.url());
    43         System.out.println("dataSource:" + annotation.dataSource());
    44         System.out.println("remarks:" + annotation.remarks());
    45        return proceed; 
    46     }
    47 
    48     /**
    49      * 获取方法中声明的注解信息
    50      *
    51      * @param joinPoint
    52      * @return
    53      * @throws NoSuchMethodException
    54      */
    55     public RecordRpc getDeclaredAnnotation(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
    56         // 获取方法名
    57         String methodName = joinPoint.getSignature().getName();
    58         // 反射获取目标类
    59         Class<?> targetClass = joinPoint.getTarget().getClass();
    60         // 拿到方法对应的参数类型
    61         Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
    62         // 根据类、方法、参数类型(重载)获取到方法的具体信息
    63         Method objMethod = targetClass.getMethod(methodName, parameterTypes);
    64         // 拿到方法定义的注解信息
    65         RecordRpc annotation = objMethod.getDeclaredAnnotation(RecordRpc.class);
    66         // 返回
    67         return annotation;
    68     }
    69 }

      第四步:注解使用

       结果展示:

       大家看明白了吗?如果大家设计api开放接口,在设计鉴权这块的时候 ,也是可以通过自定义注解来完成哦,其核心的思想是将公共的操作抽取出来,也就是面向切面编程的思想。

     参考:https://www.cnblogs.com/lingyejun/p/9941350.html

  • 相关阅读:
    命令模式
    装饰者模式
    迭代器模式-统一集合的遍历方式
    springboot源码解析-管中窥豹系列之总体结构
    启动项目tomcat报错
    在项目中部署redis的读写分离架构(包含节点间认证口令)
    Redis的几个核心机制底层原理
    Java内存模型
    JAVA原子组件和同步组件
    DataGrid 删除一行数据
  • 原文地址:https://www.cnblogs.com/maguanyue/p/11712864.html
Copyright © 2011-2022 走看看