Spring注解配置AOP切面实现注解切点记录方法执行日志和时间_注解在aop中的应用,比如配置切面日志-程序员宅基地

技术标签: spring  Java  微服务  aop  java  

1、方法执行日志方案设计

1.1 注解的方式

通过定义日志注解+解析注解的方式来实现记录方法执行日志,这种方式在需要监控的接口实现方法上打上定义的注解,再通过解析注解的方式将日志记录到文件。

注解方式的优点粒度细,在需要监控的服务接口实现方法打上注解就可以实现记录日志。缺点是服务接口太多的话,每一个接口都需要打上注解,比较繁琐。

定义注解
import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    
    String value() default "";
}
注解解析
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;


@Aspect
@Order(5)
@Component
public class LogAspect {
    
    /**
     * 记录开始时间
     */
    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);


    @Pointcut("@annotation(xx.Log)")
    public void log(){
    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) {
    
        long current = System.currentTimeMillis();
        startTime.set(current);

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        LogUtil.info(LOGGER, "方法名称:", method.getName(), "method parameter:", method.getParameterTypes(), ",start time:", current);
    }


    @AfterReturning(returning="returnValue", pointcut = "log()")
    public void doAfterReturning(Object returnValue) {
    
        long gap = System.currentTimeMillis() - startTime.get();
        LogUtil.info(LOGGER, "returnValue:" + JSON.toJSONString(returnValue), ",gap:", gap);
    }
}

2.2 AOP的方式

通过AOP的方式来实现,对集成层服务接口的包定义切点切面,当调用服务时实际会调用的代理对象的方法,可以在前置和后置方法中实现日志的记录。AOP的方式的优点是粒度较粗,可以直接对包下面的所有服务全部记录日志。缺点是不能实现细粒度的日志记录。

切面方式
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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.junit.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Order(5)
@Component
public class LogAspect {
    

    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);

		//包及其子包执行
    @Pointcut("execution(* com.package..*.*(..))")
    public void log(){
    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) {
    
        startTime.set(System.currentTimeMillis());

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log mylog = method.getAnnotation(Log.class);
    }

    @Around("log()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    

    }

    @AfterReturning(returning="returnValue", pointcut = "log()")
    public void doAfterReturning(Object returnValue) {
    
        long gap = System.currentTimeMillis() - startTime.get();
        System.out.println("returnValue:" + returnValue);
    }
}

2.3 xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
	   default-autowire="byName">

	<!--开启注解扫描-->
	<context:component-scan base-package="com.package.xx"/>
	<!--开启AOP自动代理,默认为false-->
	<aop:aspectj-autoproxy />

</beans>
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lovequanquqn/article/details/107826924

智能推荐

js手写题——高阶函数&函数柯里化&compose函数&ES6装饰器_js 装饰器和高阶函数-程序员宅基地

文章浏览阅读225次。高阶函数以函数作为参数/以函数作为返回值/常用于作为函数装饰器常用高阶函数:防抖Debounce和节流Throttlejs手写题——防抖和节流 Promise、setTimeout等等为什么要使用高阶函数?减少非纯函数的数量,增加系统稳定性与可靠性,纯函数方便做单元测试。函数柯里化函数式编程思想,既能减少代码冗余,也能增加可读性。它利用高阶函数,通过函数调用继续返回函数的形式,将接收多个参数转换为多次接收参数最后统一处理。理解函数柯里化function curry(fn,currArgs){_js 装饰器和高阶函数

数据库的索引_稠密索引和稀疏索引的区别-程序员宅基地

文章浏览阅读348次。(一)顺序索引1. 聚集索引(主索引)和非聚集索引(辅助索引)(1)聚集索引:包含记录的文件按照某个搜索码的顺序排序。(2)非聚集索引:搜索码制定的顺序与文件中记录的物理顺序不同(搜索码不是候选码)。 2. 稠密索引和稀疏索引(1)稠密索引:文件中的每个搜索码值都有一个索引项。在稠密聚集索引中,索引项包括搜索码值以及指向具有该搜索码值的第一条数据记录的指针;在稠密非..._稠密索引和稀疏索引的区别

嵌入式系统降低功耗的设计技术_在嵌入式软件开发过程中,降低功耗有哪些措施?-程序员宅基地

文章浏览阅读5.4k次,点赞2次,收藏22次。电源通常被认为是整个嵌入式系统的“心脏”,绝大多数电子设备50%~80%的节能潜力在于电源系统。研制开发新型开关电源是节能的主要举措之一。 _在嵌入式软件开发过程中,降低功耗有哪些措施?

swift UITableView cell自适应高度_swift uitableviewcell 高度自适应-程序员宅基地

文章浏览阅读465次。http://blog.csdn.net/tujiaw/article/details/47073449http://fourfire.iteye.com/blog/2109724_swift uitableviewcell 高度自适应

清华大学 Homebrew-bottles 镜像使用帮助-程序员宅基地

文章浏览阅读1.9k次。2019独角兽企业重金招聘Python工程师标准>>> ..._homebrew bottlesh

BZOJ 2555: SubString(后缀自动机+lct)-程序员宅基地

文章浏览阅读70次。传送门解题思路  第二个操作其实就是把\(T\)在\(S\)上跑一遍匹配然后输出最后那个匹配点\(right\)集合的大小。现在考虑如何动态维护,发现\(right\)集合的转移为\(siz_{fa_i}=\sum siz_i\),那么假如一个字符其实就是给\(parent\)树上这个点的每个祖先\(+1\),这样就可以\(lct\)维护。代码#include<iostream>...

随便推点

Vue面试相关问题_error with push/replace state domexception: failed-程序员宅基地

文章浏览阅读433次。1、vue解决了什么问题解决了用 DOM API 操作 UI 过于反人类的问题。React 通过 UI = f(data) 解决。Vue 通过 Reactive 响应式数据解决。更多关于上述问题理解2、MVVM的理解MVVM分为Model、View、ViewModel三者。Model:代表数据模型,数据和业务逻辑都在Model层中定义;View:代表UI视图,负责数据的展示;ViewModel:就是与界面(view)对应的Model。因为,数据库结构往往是不能直接跟界面控件一一对应上的_error with push/replace state domexception: failed to execute 'pushstate' on

使用自有数据集微调ChatGLM2-6B_chatglm微调自己的数据集-程序员宅基地

文章浏览阅读1.9k次,点赞38次,收藏32次。P-Tuning v2的原理是通过对已训练好的大型语言模型进行参数剪枝,得到一个更加小巧、效率更高的轻量级模型。具体地,P-Tuning v2首先使用一种自适应的剪枝策略,对大型语言模型中的参数进行裁剪,去除其中不必要的冗余参数。然后,对于被剪枝的参数,P-Tuning v2使用了一种特殊的压缩方法,能够更加有效地压缩参数大小,并显著减少模型微调的总参数量。_chatglm微调自己的数据集

GNU gettext utilities-程序员宅基地

文章浏览阅读3.4k次。Table of Contents1 Introduction1.1 The Purpose of GNUgettext1.2 I18n, L10n, and Such1.3 Aspects in Native Language Support1.4 Files Conveying Translations1.5 Overview of GNUgettext2 Th_gnu gettext utilities

全连接-普通卷积-深度可分离卷积-分组卷积-计算量和参数量_卷积取代全连接运算后需要学习的参数-程序员宅基地

文章浏览阅读1.8k次。全连接-普通卷积-深度可分离卷积-分组卷积-计算量和参数量一个全连接的参数量:params=(Ni+1)×No params=(N_i+1)\times{N_o} params=(Ni​+1)×No​其中,NiN_iNi​ 表示输入特征向量权重个数,NoN_oNo​ 表示输出特征向量的权重个数,+1表示偏置,直接理解参数量与输入输出个数有关。一个全连接的计算量:FLOPs=[Ii+(Ii−1)+1]×Io FLOPs= [I_i+(I_i-1)+1]\times{I_o} FLOP_卷积取代全连接运算后需要学习的参数

VS2005(VC++)远程调试方法_vs++2005-程序员宅基地

文章浏览阅读1k次。仅我目前了解很多人还在使用成本很高的本地调试方法——即在需要调试的机器上安装VS环境。这样的好处就是直接,但是成本很高,要在目标机器安装一个VS的Copy(国内可能不是问题:) 。还有源代码安全问题、同步问题等等!开始!已知:A、B两个服务器。如果是XP必须为最新的SP,2003的任意版本均可,是为了解决DCOM的通讯问题。A为开发用机,安装VS2005团队开发版。B为_vs++2005

01.VS2017安装与配置_visual c++2017安装-程序员宅基地

文章浏览阅读301次。4 单个组件->关键字MFC-> 带Spectre缓解措拖Visual C++ MFC for x86/x64。3 其它工具集->Visual studio 扩展开发。2 用于x86和x64的Visual C++ MFC。1 Windows->使用C++的桌面开发。1.VS2017安装。_visual c++2017安装

推荐文章

热门文章

相关标签