无感数据埋点(自定义注解+aop+异步)

  前段时间,由于业务上需求,需要对客户端的请求数据进行埋点,以方便后续处理分析用户的访问数据喜好。埋点业务尽可能是异步解耦,即对主流程业务无影响。经过一番思考,决定采用自定义注解+aop+异步方式进行处理。

  • 元注解

  实现自定义注解,先了解下元注解。元注解是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释。常用的元注解有4种:

@Target:描述了注解修饰的对象范围,取值在java.lang.annotation.ElementType定义,常用的包括:

  • METHOD:用于描述方法
  • PACKAGE:用于描述包
  • PARAMETER:用于描述方法变量
  • TYPE:用于描述类、接口或enum类型

@Retention: 表示注解保留时间长短。取值在java.lang.annotation.RetentionPolicy中,取值为:

  • SOURCE:在源文件中有效,编译过程中会被忽略
  • CLASS:随源文件一起编译在class文件中,运行时忽略
  • RUNTIME:在运行时有效

只有定义为RetentionPolicy.RUNTIME时,才能通过注解反射获取到注解。

@Documented:用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中。

@Inherited:表示注释类型是自动继承的,该注释除类之外的任何内容均无效,即父和子均为类才能有作用。

自定义一个注解接口:
 1 import java.lang.annotation.*;
 2 
 3 @Retention(RetentionPolicy.RUNTIME)
 4 @Target({ElementType.METHOD, ElementType.TYPE})
 5 @Documented
 6 public @interface SysLog {
 7 
 8     String domain() default "strategy";
 9 
10     String platform() default "strategy-service";
11 
12     String action() default "";
13 
14 }
View Code

实现AOP切面拦截:

 1 import com.alibaba.fastjson.JSONObject;
 2 import com.shimao.iot.strategy.service.strategyservice.service.DataPointLogService;
 3 import lombok.extern.slf4j.Slf4j;
 4 import org.aspectj.lang.JoinPoint;
 5 import org.aspectj.lang.annotation.AfterReturning;
 6 import org.aspectj.lang.annotation.Aspect;
 7 import org.aspectj.lang.annotation.Before;
 8 import org.aspectj.lang.annotation.Pointcut;
 9 import org.aspectj.lang.reflect.MethodSignature;
10 import org.springframework.stereotype.Component;
11 
12 import javax.annotation.Resource;
13 
14 @Aspect
15 @Component
16 @Slf4j
17 public class SysLogAspect {
18 
19     @Resource
20     private DataPointLogService dataPointLogService;
21 
22  
23    // 定义切点   
24    @Pointcut("@annotation(xxx.dataPoint.SysLog)")
25     public void sysLogAspect() {
26     }
27     
28     // 前置通知,拦截controller层请求
29     @Before(value = "sysLogAspect()")
30     public void doBefore(JoinPoint joinPoint) {
31         String methodName = joinPoint.getSignature().getName();
32         String request = JSONObject.toJSONString(joinPoint.getArgs()[0]);
33         log.info(methodName + " request data:{}", request);
34         SysLog sysLog = ((MethodSignature)joinPoint.getSignature()).getMethod().getAnnotation(SysLog.class);
35         dataPointLogService.recordLog(sysLog.domain(), sysLog.platform(), sysLog.action(), request);
36 
37     }
38 
39     //后置通知,输出响应结果数据
40     @AfterReturning(returning = "ret", pointcut = "sysLogAspect()", argNames = "joinPoint,ret")
41     public void doAfterReturning(JoinPoint joinPoint, Object ret) {
42         String className = joinPoint.getTarget().getClass().getName();
43         String methodName = joinPoint.getSignature().getName();
44         log.info(className + "." + methodName + " result:{}", JSONObject.toJSONString(ret));
45     }
46 
47 }
View Code

定义异步接口记录处理埋点数据:

1 public interface DataPointLogService {
2 
3     void recordLog(String domain, String platform, String action, String content);
4 }
View Code
 1 @Service
 2 public class DataPointLogServiceImpl implements DataPointLogService {
 3 
 4 
 5     @Override
 6     @Async
 7     public void recordLog(String domain, String platform, String action, String content) {
 8         PointDataUtils.addLogData("", "", domain, platform, action, content, "");
 9     }
10 }
View Code

 controller层通过注解接入埋点业务:

无感数据埋点(自定义注解+aop+异步)

相关推荐