现在有这样一种常见,系统中有一个接口,该接口执行的方法忽快忽慢,因此你需要去统计改方法的执行时间。刚开始你的代码可能如下:

          long start = System.currentTimeMillis();
somemethod();
long end = System.currentTimeMillis();
System.out.println(end-start);

这个方式能够打印方法执行的时间,可是疑问来了,如果系统中很多方法都需要计算时间,都需要重复这样的代码?这个时候,你可以考虑注解,通过aop去计时。

在项目中添加如下依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

  定义一个注解MethodStats,所有加上此注解的方法可以打印方法执行的时间。

package com.example.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodStats {
}

  定义一个拦截类,通过此拦截类,可以统计有注解的方法的执行时间。

package com.example.demo;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component; @Aspect
@Component
public class TimeLogger
{
Logger logger = LoggerFactory.getLogger(getClass()); @Around("@annotation(com.example.demo.MethodStats)")
public Object log(ProceedingJoinPoint point) throws Throwable
{
long start = System.currentTimeMillis();
Object result = point.proceed();
logger.info("className={}, methodName={}, timeMs={},threadId={}",new Object[]{
MethodSignature.class.cast(point.getSignature()).getDeclaringTypeName(),
MethodSignature.class.cast(point.getSignature()).getMethod().getName(),
System.currentTimeMillis() - start,
Thread.currentThread().getId()}
);
return result;
}
}

  下面是一个测试:

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
public class HelloController { // 防在这里可以拦截
@GetMapping("/")
@MethodStats
public String hello2() {
return "hello2";
} }

  现在假设,我们需要方法必须在一定时间内执行完,如果没有执行完强制返回,我们现在就需要给注解添加一个时间的变量。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodStats {
public int time() default -1;
}

 相应的拦截器的方法做如下处理:

package com.example.demo;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import javax.rmi.CORBA.Tie; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component; @Aspect
@Component
public class TimeLogger {
Logger logger = LoggerFactory.getLogger(getClass()); @Around("@annotation(com.example.demo.MethodStats)")
public Object log(ProceedingJoinPoint point) throws Throwable {
long start = System.currentTimeMillis(); int time = MethodSignature.class.cast(point.getSignature()).getMethod().getAnnotation(MethodStats.class).time(); if (time > 0) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Object> future = executor.submit(new Callable<Object>() {
public Object call() throws Exception {
Object result = null;
try {
result = point.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
});
try {
future.get(time, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
// do something or log it
} finally {
future.cancel(true);
logger.info("cancel");
} } else {
Object result = point.proceed();
logger.info("className={}, methodName={}, timeMs={},threadId={}",
new Object[] { MethodSignature.class.cast(point.getSignature()).getDeclaringTypeName(),
MethodSignature.class.cast(point.getSignature()).getMethod().getName(),
System.currentTimeMillis() - start, Thread.currentThread().getId() });
return result;
}
return null;
}
}

  

主要思路使用Future去控制方法的执行时间,上述样例仅供学习测试,如果在线上环境,请使用hystrix,hystrix提供了晚上的failback。需要特别注意的是,spring 的事务提供了timeout的注解,可以控制事务的执行时间。

ARTS打卡计划第二周-Share-使用java注解对方法计时的更多相关文章

  1. ARTS打卡计划第二周

    Algorithms: https://leetcode-cn.com/problems/3sum/ 算法是先排序,然后按照两个数和两边逼中,考虑去重. Review: https://www.inf ...

  2. ARTS打卡计划第二周-Review

    本周review的文章是:https://medium.com/@hakibenita/optimizing-django-admin-paginator-53c4eb6bfca3 改篇文章的题目是: ...

  3. ARTS打卡计划第二周-Tips-mysql-binlog-connector-java的使用

    最近发现一个挺不错的框架mysql-binlog-connector-java,可以实时监控binlog的变化. 首先检查mysql的binlog是否开启,在开启的情况下: 引入依赖 <depe ...

  4. ARTS打卡计划第二周-Algorithm

    665. 非递减数列  https://leetcode-cn.com/problems/non-decreasing-array/ 给定一个长度为 n 的整数数组,你的任务是判断在最多改变 1 个元 ...

  5. ARTS打卡计划第九周

    Algorithms: https://leetcode-cn.com/problems/merge-two-sorted-lists/submissions/ 合并两个链表 Review:  “Pu ...

  6. ARTS打卡计划第一周

    Algorithms: https://leetcode-cn.com/problems/two-sum/ Review: https://www.infoq.cn/article/EafgGJEtq ...

  7. ARTS打卡计划第一周-Share-系统字典模块的设计

    在软件开发的过程,经常有一些类型的字段信息:性别.学历.职级.车辆类别.公司类型.结算类型等.这些字段有2个特征:1是字段可选的类型是有限,2是字段可能会变化,我们把这种字段描述为字段字段.  本篇文 ...

  8. ARTS打卡计划第一周-Tips-ControllerAdvice的使用

    通常在开发具体项目过程中我们可能会面临如下问题: 统一所有的json返回结果 统一处理所有controller中的异常,并且给不同异常不同的返回状态值 统一对返回的接口做数据校验或者加密,防止篡改 在 ...

  9. ARTS打卡计划第一周-Review

    本周分享的文章来自于medium的 Testing Best Practices for Java + Spring Apps 这个文章主要讲的是java测试的一些最佳实践 1.避免函数返回void, ...

随机推荐

  1. css 实现等分布局

    目前移动版等分布局最常用的是 flex 等分,pc 端上用得更多则是 float. 假设父元素下有 3 个子元素,每个子元素相隔 24px,子元素等分父元素宽度 实现:float + margin ( ...

  2. 联想扬天3900c电脑BIOS设置U盘启动图文教程

    有联想扬天3900c的用户反映说,制作好U大侠U盘后,按快捷键却识别不到U盘,不能进行U盘启动,这是怎么回事呢?其实这是BIOS设置的问题,下面U大侠教大家如何对联想扬天3900c电脑进行BIOS设置 ...

  3. 工控随笔_20_西门子_WinCC的VBS脚本_09_常量和流程控制_02

    vbs不但提供了分支结构,还提供了丰富的循环形式.一共有3种循环: 1.for循环 2.do...loop循环 3.while循环 各种循环有各自的特点,在使用的时候可以进行转换. 前面已经描述过Fo ...

  4. vmware 中配置centos 7 静态IP

    虚拟机配置成静态IP可以保证每次宿主机器重启后,虚拟机的IP保持不变,这对于学习集群环境下的软件(如hadoop集群,mysql等数据库集群)很有用. vmware workstation 中装好li ...

  5. Spring的IOC原理

    1. IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 图1:软件系统中耦合的对象 如果我们打开机 ...

  6. 为什么HTML中的多个空格或是回车在浏览器上只能显示出一个?

    我们在学习HTML的时候可能书本或是老师会告诉我们一件事,就是在HTML中不管我们在两个文本之间加上多少连续的空格或是回车,到了浏览器里面只能显示出一个来.但是我们从来不知道为什么. 原因很简单,因为 ...

  7. Error in loadNamespace 的解决之道

    Error in loadNamespace(j <- i[[1L]], c(lib.loc, .libPaths()), versionCheck = vI[[j]])   在构建比较复杂的环 ...

  8. Linux系统编程——水平触发和边沿触发

    事件模型 EPOLL事件有两种模型: Edge Triggered (ET) 边缘触发只有数据到来才触发,不管缓存区中是否还有数据. Level Triggered (LT) 水平触发只要有数据都会触 ...

  9. [UE4]VR手柄按键参考

    一.VR手柄按键 二.Gamepad菜单往下拉 三.Shouder Button,在一般游戏当中是用作菜单键,按一下Shouder Button会出现游戏菜单. 四.Face Buttons:可以触摸 ...

  10. 软件测试:3.Exercise Section 2.3

    软件测试:3.Exercise Section 2.3 /************************************************************ * Finds an ...