自定义 Spring 通用日志注解()

  本篇文章为你整理了自定义 Spring 通用日志注解()的详细内容,包含有 自定义 Spring 通用日志注解,希望能帮助你了解 自定义 Spring 通用日志注解。

  目录自定义 Spring 通用日志注解1. 注解@Metrics2. 切面MetricsAspect3. 自动注入AutoConfiguration4. 配置文件MetricsProperties5. 其它配置配置自动注入配置文件提示

  自定义 Spring 通用日志注解

  1. 注解@Metrics

  

@Retention(RetentionPolicy.RUNTIME)

 

  @Target({ElementType.METHOD, ElementType.TYPE})

  public @interface Metrics {

   * 在方法成功执行后打点,记录方法的执行时间发送到指标系统,默认开启

   boolean recordSuccessMetrics() default true;

   * 在方法成功失败后打点,记录方法的执行时间发送到指标系统,默认开启

   boolean recordFailMetrics() default true;

   * 通过日志记录请求参数,默认开启

   boolean logParameters() default true;

   * 通过日志记录方法返回值,默认开启

   boolean logReturn() default true;

   * 出现异常后通过日志记录异常信息,默认开启

   boolean logException() default true;

   * 出现异常后忽略异常返回默认值,默认关闭

   boolean ignoreException() default false;

  

 

  2. 切面MetricsAspect

  

@Aspect

 

  @Slf4j

  @Order(Ordered.HIGHEST_PRECEDENCE)

  public class MetricsAspect {

   * 让Spring帮我们注入ObjectMapper,以方便通过JSON序列化来记录方法入参和出参

   @Resource

   private ObjectMapper objectMapper;

   * 实现一个返回Java基本类型默认值的工具。其实,你也可以逐一写很多if-else判断类型,然后手动设置其默认值。

   * 这里为了减少代码量用了一个小技巧,即通过初始化一个具有1个元素的数组,然后通过获取这个数组的值来获取基本类型默认值

   private static final Map Class ? , Object DEFAULT_VALUES = Stream

   .of(boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, short.class)

   .collect(toMap(clazz - clazz, clazz - Array.get(Array.newInstance(clazz, 1), 0)));

   public static T T getDefaultValue(Class T clazz) {

   //noinspection unchecked

   return (T) DEFAULT_VALUES.get(clazz);

   * 标记了Metrics注解的方法进行匹配

   @Pointcut("@annotation(com.common.config.metrics.annotation.Metrics)")

   public void withMetricsAnnotationMethod() {

   * within指示器实现了匹配那些类型上标记了@RestController注解的方法

   * 注意这里使用了@,标识了对注解标注的目标进行切入

   @Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")

   public void controllerBean() {

   @Pointcut("@within(com.common.config.metrics.annotation.Metrics)")

   public void withMetricsAnnotationClass() {

   @Around("controllerBean() withMetricsAnnotationMethod() withMetricsAnnotationClass()")

   public Object metrics(ProceedingJoinPoint pjp) throws Throwable {

   // 通过连接点获取方法签名和方法上Metrics注解,并根据方法签名生成日志中要输出的方法定义描述

   MethodSignature signature = (MethodSignature) pjp.getSignature();

   Metrics metrics = signature.getMethod().getAnnotation(Metrics.class);

   String name = String.format("【%s】【%s】", signature.getDeclaringType().toString(), signature.toLongString());

   if (metrics == null) {

   @Metrics

   final class InnerClass {

   metrics = InnerClass.class.getAnnotation(Metrics.class);

   // 尝试从请求上下文获得请求URL

   RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

   if (requestAttributes != null) {

   HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();

   name += String.format("【%s】", request.getRequestURL().toString());

   // 入参的日志输出

   if (metrics.logParameters()) {

   log.info(String.format("【入参日志】调用 %s 的参数是:【%s】", name, objectMapper.writeValueAsString(pjp.getArgs())));

   // 连接点方法的执行,以及成功失败的打点,出现异常的时候记录日志

   Object returnValue;

   Instant start = Instant.now();

   try {

   returnValue = pjp.proceed();

   if (metrics.recordSuccessMetrics()) {

   // 在生产级代码中,应考虑使用类似Micrometer的指标框架,把打点信息记录到时间序列数据库中,实现通过图表来查看方法的调用次数和执行时间,

   log.info(String.format("【成功打点】调用 %s 成功,耗时:%d ms", name, Duration.between(start, Instant.now()).toMillis()));

   } catch (Exception ex) {

   if (metrics.recordFailMetrics()) {

   log.info(String.format("【失败打点】调用 %s 失败,耗时:%d ms", name, Duration.between(start, Instant.now()).toMillis()));

   if (metrics.logException()) {

   log.error(String.format("【异常日志】调用 %s 出现异常!", name), ex);

   if (metrics.ignoreException()) {

   returnValue = getDefaultValue(signature.getReturnType());

   } else {

   throw ex;

   // 返回值输出

   if (metrics.logReturn()) {

   log.info(String.format("【出参日志】调用 %s 的返回是:【%s】", name, returnValue));

   return returnValue;

  

 

  3. 自动注入AutoConfiguration

  

@AutoConfiguration

 

  @Slf4j

  @EnableConfigurationProperties(MetricsProperties.class)

  @ConditionalOnProperty(prefix = "common.metrics", name = {"keep-alive"}, havingValue = "true", matchIfMissing = true)

  public class AspectAutoConfiguration {

   public AspectAutoConfiguration() {

   log.info("AspectAutoConfiguration initialize.");

   @Bean

   public MetricsAspect metricsAspect() {

   return new MetricsAspect();

  

 

  4. 配置文件MetricsProperties

  

@ConfigurationProperties(prefix = "common.metrics")

 

  public class MetricsProperties {

   public Boolean getKeepAlive() {

   return keepAlive;

   public void setKeepAlive(Boolean keepAlive) {

   this.keepAlive = keepAlive;

   private Boolean keepAlive = true;

  

 

  5. 其它配置

  配置自动注入

  配置resource.META-INF.spring.org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,增加RunsOnProfilesAutoConfiguration类路径。

  配置文件提示

  

{

 

   "groups": [],

   "properties": [

   "name": "common.metrics.keepAlive",

   "type": "java.lang.Boolean",

   "sourceType": "com.common.config.metrics.properties.MetricsProperties"

  

 

  以上就是自定义 Spring 通用日志注解()的详细内容,想要了解更多 自定义 Spring 通用日志注解的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: