记录一次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

posted @ 2019-10-21 12:49  一马关月  阅读(339)  评论(0编辑  收藏  举报