Spring的AOP使用场景之性能监控

本文介绍了如何通过AOP切面和自定义注解来监控Java方法的执行时间。首先创建了一个名为TimeCostRecord的注解,然后定义了一个TimeCostRecordAspect切面,使用@Around注解拦截标记了TimeCostRecord的方法,记录方法开始和结束时间以计算执行耗时,并在日志中输出。最后展示了如何在需要监控的方法上使用该注解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模块执行时间监控
想要了解各个接口具体执行时间,需要计算方法执行开始到方法执行结束所用的时间,下面通过AOP+注解的方式来实现此功能。想要获取方法执行的时间只需加上注解即可。

首先新建注解

/**
 * 功能说明:监控注解
 *
 * @return <br>
 *     1.[2021年09月10日下午13:50] 创建方法 by wheree
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TimeCostRecord {}

其次创建AOP切面

@Component
public class TimeCostRecordAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(TimeCostRecordAspect.class);

    // 定义一个切入点
    @Pointcut("@annotation(com.wheree.common.utils.aop.TimeCostRecord)")
    private void timeCostRecordAspect() {}

    /**
     * 功能说明:TODO
     *
     * @return <br>
     *       [2021年09月10日下午13:50] 创建方法 by wheree
     * @params
     */
    @Around("timeCostRecordAspect()")
    public Object recordSystemLog(ProceedingJoinPoint pjp) throws Throwable {

        // 方法通知前获取时间,为什么要记录这个时间呢?当然是用来计算模块执行时间的
        long start = System.currentTimeMillis();
        long end = 0L;
        // 拦截的实体类,就是当前正在执行的controller
        Object target = pjp.getTarget();
        // 拦截的方法名称。当前正在执行的方法
        String methodName = pjp.getSignature().getName();
        // 拦截的方法参数
        Object[] args = pjp.getArgs();
        if (null != args && args.length == 1) {
            LOGGER.debug(
                    "target:{} method: {} 调用的参数是 {} ",
                    target,
                    methodName,
                    JsonUtils.obj2json(args[0]));
        }
        // 拦截的放参数类型
        Signature sig = pjp.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw ServiceException.buildInternalException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod().getParameterTypes();

        Object object = null;
        // 获得被拦截的方法
        Method method = null;
        try {
            method = target.getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e1) {
            // TODO Auto-generated catch block
            LOGGER.error("recordSystemLog error {}", e1);
        } catch (SecurityException e1) {
            // TODO Auto-generated catch block
            LOGGER.error("recordSystemLog error {}", e1);
        }

        if (null != method) {
            // 判断是否包含自定义的注解,说明一下这里的SystemLog就是我自己自定义的注解
            if (method.isAnnotationPresent(TimeCostRecord.class)) {
                TimeCostRecord systemLogger = method.getAnnotation(TimeCostRecord.class);
                try {
                    object = pjp.proceed();

                } catch (Throwable e) {
                    LOGGER.error("method proceed error", e);
                    LOGGER.error("method {} param {}", methodName, JsonUtils.obj2json(args));
                    throw e;
                } finally {
                    end = System.currentTimeMillis();
                    // TODO: 2021/9/28 日志记载
                    LOGGER.debug(
                            "target:{} method: {} cost {} ms", target, methodName, (end - start));
                            //TODO 如有需要可在此执行持久化操作
                }
            } else { // 没有包含注解
                object = pjp.proceed();
            }
        } else { // 不需要拦截直接执行
            object = pjp.proceed();
        }
        LOGGER.debug(
                "target:{} method: {} 执行的结果是:{}", target, methodName, JsonUtils.obj2json(object));
        return object;
    }

最后添加在需要监控的方法上

@TimeCostRecord
@Override
    public BaseResult test(TestModel model) {
    //dosomethings
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值