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