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

  • 相关阅读:
    Codeforces467C George and Job
    Codeforces205E Little Elephant and Furik and RubikLittle Elephant and Furik and Rubik
    Codeforce205C Little Elephant and Interval
    51nod1829 函数
    51nod1574 排列转换
    nowcoder35B 小AA的数列
    Codeforce893E Counting Arrays
    gym101612 Consonant Fencity
    CodeForces559C Gerald and Giant Chess
    CodeForces456D A Lot of Games
  • 原文地址:https://www.cnblogs.com/maguanyue/p/11712864.html
Copyright © 2011-2022 走看看