zoukankan      html  css  js  c++  java
  • SpringAOP+自定义注解实现日志记录

    SpringAOP+自定义注解实现日志记录

    关于自定义注解基本介绍可参考以往博客https://www.cnblogs.com/DFX339/p/11386722.html

    此文主要是讲述如何通过注解标识记录日志信息,一般我们的Service接口都需要记录入参信息,参数校验,方法执行时间等

    处理思路:

    1.自定义注解,使用的时候通过加入注解即可注入相应的日志信息

    2.使用SpringAOP, 识别注解标识的方法,切入日志信息

    步骤一: 定义注解类 SystemLog.java 

    package com.im.nexus.service.utils.logUtils;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @description:系统日志注解(使用在Service类里面的方法上)
     * @author: duanfeixia
     * @time: 2020/5/12 10:54
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface SystemLog {
        String methoddesc() default "";//方法描述
    }
    

    步骤二:定义切面 SystemLogAspect.java

    这里切记需要加入 @Component @Aspect 这两个注解,@Slf4j 这个注解是日志类的注解 非必选

    package com.im.nexus.service.utils.logUtils;
    
    
    import com.google.gson.Gson;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 自定义日志注解 SystemLog配合AOP注入日志信息
     */
    @Component
    @Aspect
    @Slf4j
    public class SystemLogAspect {
    
        // @SystemLog标识为切入点,切面会根据@SystemLog注解来注入数据
        @Pointcut("@annotation(com.imodule.nexus.service.utils.logUtils.SystemLog)")
        public void logPointCut(){
        }
    
        //环绕注入
        @Around("logPointCut()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            long startTime = System.currentTimeMillis();//记录目标方法的开始执行时间
            Object result = point.proceed();//执行目标方法
            long methodexecutetime = System.currentTimeMillis() - startTime;
    
            //日志信息记录
            try {
                MethodSignature methodSignature = (MethodSignature) point.getSignature();
                Method method = methodSignature.getMethod();
                SystemLog systemLog = method.getDeclaredAnnotation(SystemLog.class);
                String className = point.getTarget().getClass().getName();//类名
                String methodName = method.getName();//方法名
    
                //入参信息
                Object[] args = point.getArgs();
                List<String> list = new ArrayList<String>();
                for (Object obj : args) {
                        list.add(new Gson().toJson(obj));
                }
                log.info(className+"."+methodName+","+systemLog.methoddesc()+",入参:"+list.toString());
                log.info(className+"."+methodName+","+systemLog.methoddesc()+",耗时:"+methodexecutetime+"ms");
            } catch (Exception e) {
                log.error("日志切入出错");
            }
            return result;
        }
    }
    

      

    步骤三: 在具体Service实现类的方法上使用 @SystemLog注解

    使用示例:@SystemLog(methoddesc = "方法说明内容")

    package com.im.nexus.service.impl.prd;
    
    import com.im.common.frame.exception.IMException;
    import com.im.nexus.constant.NexusExceptionCodeEnum;
    import com.im.nexus.dao.prd.PrdTsarateMapper;
    import com.im.nexus.service.utils.BizParamCheckUtils;
    import com.im.nexus.service.utils.ExceptionThrowUtils;
    import com.im.nexus.service.utils.logUtils.SystemLog;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * @description 产品接口实现类
     * @date 2020-03-31
     * @author duanfeixia
     */
    @Service
    @Slf4j
    public class prdServiceImpl implements prdService {
        
        @Autowired
        private PrdTsarateMapper prdTsarateMapper;
        
        @Override
        @SystemLog(methoddesc = "是否简易核保-注解标识")
        public PrdResultDTO isSimple(String prdCode) throws IMException {
            //入參對象校驗
            BizParamCheckUtils.paramPropertyNullCheck("prdServiceImpl.getPrdStaticInfo:prdCode",prdCode);
            
        	PrdResultDTO prdResultDTO= new PrdResultDTO();
            try {
                Integer prdflag = prdTsarateMapper.isSimple(prdCode);
                /// 这里遵照了以前的写法,建议后续使用 1:是,0:否
                if (null != prdflag && prdflag > 0) {
                    // 屬於簡易核保 : 0
                	prdResultDTO.setIsSimple(SysCnst.STR_FLAG_NO);
                } else {
                    // 不屬於簡易核保 : 1
                	prdResultDTO.setIsSimple(SysCnst.STR_FLAG_YES);
                }
            } catch (Exception e) {
                log.error("prdServiceImpl.isSimple exception:[prdcode=" + prdCode + "]");
                ExceptionThrowUtils.logAndThrowException(NexusExceptionCodeEnum.EXCEPTION_DB_000001, e);
            }
            return prdResultDTO;
        }
    }
    

      

    步骤四:定义测试类,对以上方法进行测试(Junit单元测试)

    package com.im.nexus.service.prd;
    
    import com.im.common.frame.exception.IMException;
    import com.im.nexus.DTO.prd.*;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    public class prdServiceTest {
    
        @Autowired
        private prdService prdService;
    
        @Test
        public void testisSimple() throws IMException{
        	try {
                PrdResultDTO prdTsarateRtl = prdService.isSimple("12");
                log.info("是否简易核保:"+prdTsarateRtl);
                log.info("prdTsarateRtl.getIsSimple:"+prdTsarateRtl.getIsSimple());
    		} catch (Exception e) {
    			log.error("ceshi :", e);
    		}
        }
    }
    

    执行单元测试后,测试结果如下:

    [] 2020-05-12 12:59:33:331  INFO [main] c.i.n.s.u.logUtils.SystemLogAspect 51 - com.im.nexus.service.impl.prd.prdServiceImpl.isSimple,是否简易核保-PRD,入参:["12"]
    [] 2020-05-12 12:59:33:331  INFO [main] c.i.n.s.u.logUtils.SystemLogAspect 52 - com.im.nexus.service.impl.prd.prdServiceImpl.isSimple,是否简易核保-PRD,耗时:66ms
    [] 2020-05-12 12:59:33:331  INFO [main] c.i.n.service.prd.prdServiceTest 26 - 是否简易核保:PrdTsarateRtl{isSimple=1}
    [] 2020-05-12 12:59:33:331  INFO [main] c.i.n.service.prd.prdServiceTest 27 - prdTsarateRtl.getIsSimple:1 

    前面两行则是我们通过@SystemLog注解注入的日志内容

    后面两行则是我们在Service实现类的方法中手写的日志内容

      

      

  • 相关阅读:
    asp.net core系列 76 Apollo 快速安装模式下填坑和ASP.NetCore结合使用
    asp.net core系列 75 Elasticsearch与中文分词配置
    asp.net core系列 74 Exceptionless服务端安装
    nginx for windows
    asp.net core系列 73 Exceptionless+Nlog以及Apollo介绍
    asp.net core系列 72 Exceptionless使用介绍
    asp.net core系列 71 Web架构分层指南
    asp.net core系列 70 即时通迅-WebSocket+Redis发布订阅
    asp.net core系列 69 Amazon S3 资源文件上传示例
    asp.net core系列 68 Filter管道过滤器
  • 原文地址:https://www.cnblogs.com/DFX339/p/12875544.html
Copyright © 2011-2022 走看看