zoukankan      html  css  js  c++  java
  • 利用AOP与ToStringBuilder简化日志记录

    刚学spring的时候书上就强调spring的核心就是ioc和aop blablabla......

    IOC到处都能看到...AOP么刚开始接触的时候使用在声明式事务上面..当时书上还提到一个用到aop的例子.那就是用aop去简化日志记录.

    当初有点疑问,如果这个日志是由aop来记录的,那记录的信息应该是很通用的,不是每个类定制的,那能记录一些什么信息呢?到底能有多详细的日志呢?

    于是真正开始做项目的时候关注了一下公司到时是怎么做的.....

    利用AOP记录关键方法的入参与返回

    spring aop的语法我就不列举了,网上一大堆...公司主要用他记录Controller Facade 与 service等关键方法的入参与返回.

     1 package com.labofjet.aspect;
     2 
     3 import java.util.UUID;
     4 
     5 import org.aspectj.lang.ProceedingJoinPoint;
     6 import org.slf4j.Logger;
     7 import org.slf4j.LoggerFactory;
     8 
     9 public abstract class BaseLogAspect {
    10 
    11     private static final Logger LOGGER = LoggerFactory.getLogger(BaseLogAspect.class);
    12 
    13     protected Object doLog(ProceedingJoinPoint pjp, String type) throws Throwable {// NOSONAR
    14         UUID uuid = UUID.randomUUID();
    15         String signature = pjp.getSignature().toString();
    16         LOGGER.info("识别号[sequenceid:{}]: 调用{}方法: {}", uuid, type, signature);
    17         LOGGER.debug("识别号[sequenceid:{}]: 参数为 {}", uuid, pjp.getArgs());
    18         try {
    19             long start = System.currentTimeMillis();
    20             Object result = pjp.proceed();
    21             LOGGER.info("识别号[sequenceid:{}]: 调用{}方法: {} 成功! 返回 {}", uuid, type, signature, result);
    22             LOGGER.info("识别号[sequenceid:{}]: 调用消耗时间为[timecost:{}]", uuid, System.currentTimeMillis() - start);
    23             return result;
    24         }
    25         catch (Exception e) {
    26             LOGGER.error("识别号[sequenceid:{}]: 调用{}方法: {} 失败!", uuid, type, signature);
    27             LOGGER.error("识别号[sequenceid:{}]: 异常时输入为 {}", uuid, pjp.getArgs());
    28             LOGGER.error("识别号[sequenceid:{}]: 异常为: ", uuid, e);
    29             throw e;
    30         }
    31     }
    32 
    33 }

    上面这段代码是一个简化版本的日志记录类.利用AOP可以获取到ProceedingJoinPoint,用它可以获取到方法的签名,参数等信息,十分有用.

    上面那个BaseLogAspect只是一个基础父类,描述了通用的记录方法...那具体要记录哪些类的方法的信息呢? 这就需要我们去写个子类定义具体的日志记录规则.

     1 package com.labofjet.blogv3.aspect;
     2 
     3 import org.aspectj.lang.ProceedingJoinPoint;
     4 import org.aspectj.lang.annotation.Around;
     5 import org.aspectj.lang.annotation.Aspect;
     6 import org.slf4j.Logger;
     7 import org.slf4j.LoggerFactory;
     8 import org.springframework.stereotype.Component;
     9 
    10 import com.labofjet.aspect.BaseLogAspect;
    11 
    12 @Aspect
    13 @Component
    14 public class LogAspect extends BaseLogAspect {
    15 
    16     // private static final Logger LOGGER =
    17     // LoggerFactory.getLogger(LogAspect.class);
    18 
    19     @Around("within(@org.springframework.stereotype.Controller *)")
    20     public Object logController(ProceedingJoinPoint pjp) throws Throwable {
    21         return doLog(pjp, "Controller");
    22     }
    23 
    24     // @Around("execution(* gov.gt3.iitms.sbf..*Service.*(..))")
    25     public Object logService(ProceedingJoinPoint pjp) throws Throwable {
    26         return doLog(pjp, "Service");
    27     }
    28 
    29     // @Around("execution(* gov.gt3.iitms.sbf..*Facade.*(..))")
    30     public Object logFacade(ProceedingJoinPoint pjp) throws Throwable {
    31         return doLog(pjp, "Facade");
    32     }
    33 
    34 }

    这是一种实现,公司记录了controller,facade和service..利用的是around通知..我自己的代码比较简单,不需要这么多,我只需要记录controller的日志就行了,所以我注释掉了另外2个通知.

    BaseLogAspect是通用的日志实现,它可以在不同的项目里公用,所以可以放到基础的依赖里去,每个独立的项目依赖这个BaseLogAspect然后实现自己的记录即可.

    利用ToStringBuilder来简化参数记录

    前面看到日志记录里会把调用方法的入参和结果打印出来...打印一个对象就是调用它的toString方法..如果这个方法不被重写...那么你懂得...完全和没打印差不了多少...

    每个DTO,VO等对象都有非常非常多的属性,而且有时候还会不停的增加属性.写toString方法是一件很痛苦的事情(不过eclipse也有快捷键ctrl+alt+s再按s可以生成toString方法).因为要把对象的每个属性拼接起来,很容易错,而且很占用资源(因为String相加了很多次)比较好的做法是使用ToStringBuilder的reflectionToString方法.(ToStringBuilder是org.apache.commons.lang3下的一个类...)

    1     @Override
    2     public String toString() {
    3         return ToStringBuilder.reflectionToString(this);
    4     }

    代码非常简短,而且以后修改对象属性也不需要修改toString方法.是不是很简单呢?

    ==========20170206补==========

    eclipse里shift+alt+s然后再按s也可以快速生成toString方法

  • 相关阅读:
    Osg-地图界面显示指北针(指南针)
    学习c# 7.0-7.3的ref、fixed特性并在Unity下测试
    Linux下使用FreeBSD的ee
    C++ 中 malloc/free与 new/delete区别
    CMake 手册详解
    go 从入门到了解
    LINQ:对结果进行分组(MSDN)
    LINQ: List Contains List
    C# 如何使用log4net
    控制台程序要最后加上一句 Environment.Exit(0);
  • 原文地址:https://www.cnblogs.com/abcwt112/p/5150261.html
Copyright © 2011-2022 走看看