基于AOP的环绕通知的日志配置

一. 什么是日志?

  在服务器应用中,日志起着至关重要的作用,详细的日志记录可以使我们在寻找问题的时候一下就定位到关键位置。日志信息的关键就是明确详细的记录问题的位置和出错信息。在一个服务器接口的入口和退出之前我们往往需要对日志工具进行说明配置日志的模块,分类,过滤信息等等内容。而这些数据,却是刚好可以使用切面来进行配置。

二. 日志切面类(环绕通知)

@Component
public class SkynetLogAspect {
    protected Logger logger = LoggerFactory.getLogger(SkynetLogAspect.class);

    /**
     * 采用环绕通知的方式
     */
    public Object skyNetLog(ProceedingJoinPoint joinPoint) throws Throwable {
        String method = joinPoint.getSignature().getName();
        LoggerUtils.info(logger, "class 【{}】 method 【{}】 start.", 
                 joinPoint.getTarget().getClass().getSimpleName(), method);
        Object val = null;
        Stopwatch stopwatch = Stopwatch.createStarted();
        try {
            LogContextUtils.setModule(
                    getParentName(joinPoint.getTarget().getClass()));
            LogContextUtils.setCategory(joinPoint.getTarget().getClass().getSimpleName());                            	
            LogContextUtils.setSubCategory(method);    
            val = joinPoint.proceed();
        } catch (Exception e) {
            LoggerUtils.error(logger, "【{}】 error", e, method);
        } finally {
            stopwatch.stop();
            int elapsed = (int) stopwatch.elapsed(TimeUnit.MILLISECONDS);
            LoggerUtils.info(logger, "class 【{}】 method 【{}】 finished, {}ms, result:{}", 
            joinPoint.getTarget().getClass().getSimpleName(), method, elapsed, JSON.toJSONString(val));
			//退出方法前,清除日志配置
            LogContextUtils.removeAll();
        }
        return val;
    }

    /**
     * 通过子类的类对象查找父类或者接口
     * @param object 子类的类对象
     * @return 父类或者接口名
     */
    private String getParentName(Class<?> object) {
        String parent = object.getSuperclass().getSimpleName();
        if("Object".equals(parent)){
            Class<?>[] interfaces = object.getInterfaces();
            if(interfaces.length>0){
                //选择第一个接口
                parent = interfaces[0].getSimpleName();
            }
        }
        return parent;
    }
}

三. 日志切面的配置


	<aop:config>
	<!-- 定义切入点,对哪些方法进行拦截 -->
		<aop:pointcut expression="execution(public * com.lizi.service.*.impl.*.*(..))" id="serviceLog"/>
		<aop:pointcut expression="execution(public * com.lizi.service.spider.SpiderClient.doSpider(..))" id="integrationLog"/>
		<!-- 定义切面,对拦截的方法织入的操作-->
		<aop:aspect ref="skynetLogAspect">
			<!-- 环绕通知 -->
			<aop:around method="skyNetLog" pointcut-ref="serviceLog"/>
			<aop:around method="skyNetLog" pointcut-ref="integrationLog"/>
		</aop:aspect>
	</aop:config>
原文地址:https://www.cnblogs.com/lizijuna/p/11907393.html