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

          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("/")@MethodStatspublic 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 blocke.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的注解,可以控制事务的执行时间。

转载于:https://www.cnblogs.com/dongqiSilent/p/10787270.html

ARTS打卡计划第二周-Share-使用java注解对方法计时相关推荐

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

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

  2. 第二周、逻辑函数的表示方法及其相互转换

    第二周.逻辑函数的表示方法及其相互转换 一个逻辑函数可以用真值表.表达式.逻辑图.波形图 等方法来表示.既然它们都是表示同一种逻辑关系,显然可以 互相转换 . 由真值表写逻辑式 由表达式画逻辑图 由函 ...

  3. ARTS打卡计划第六周

    Algorithms: https://leetcode-cn.com/problems/longest-palindromic-substring/ 中心扩展法首先考虑,当然看到有个动态规划,一直很 ...

  4. ARTS打卡计划第三周-Tips

    本周分享一个好用的小工具,java-faker:https://github.com/DiUS/java-faker,相应的python:https://github.com/joke2k/faker ...

  5. ARTS打卡计划第6周-REVIEW-超越编码的避免项目失败的软技能

    https://medium.com/@viral_shah/beyond-coding-soft-skills-to-avoid-project-failures-4ed7821fa93a 做项目中 ...

  6. ARTS打卡计划第四周-ALGORITHM

    866. 回文素数 求出大于或等于 N 的最小回文素数. 回顾一下,如果一个数大于 1,且其因数只有 1 和它自身,那么这个数是素数. 例如,2,3,5,7,11 以及 13 是素数. 回顾一下,如果 ...

  7. ARTS打卡计划第四周-TIPS-自定义一个LikeFilter

    django-restframe-work的searchfilter,可以从search_fields 的一个或者多个字段中搜索,语法类似http://example.com/api/products ...

  8. “打卡上班”第二周,我这样......

    (原谅我是个标题党) 上周把那个网页写完之后,信心满满得开启今天的学习,然而,学的又是我不会滴JS难受. 1.程序的结构:顺序结构(最平常的那种,感觉也是自己接触得最多得那种) 循环结构(if--el ...

  9. 第二周 预习:Java基本语法2、面向对象入门

    1. 方法相关问题 ```java public class Main {static void changeStr(String x) {x = "xyz";}static vo ...

最新文章

  1. Intel汇编程序设计-高级过程(上)
  2. 如何在 Linux 上安装服务器管理软件 Cockpit
  3. ubuntu12.04 安装中文输入法
  4. php基础教学笔记,php学习笔记:基础知识
  5. 对不起,你以前学的 ElasticSearch 都是垃圾!
  6. idea怎么找到路径下面的js_怎么找到Win7桌面存储路径?怎么把Win7桌面转到D盘?...
  7. 浙大 PAT a1058
  8. 手动实现 NSTabViewController 的 Rect Transition 及 Propagate Title-b
  9. 小白R语言数据可视化进阶练习一
  10. 如何压缩图片大小?这几种图片压缩方法总有一款适合你
  11. 数字信号处理C语言——离散傅里叶变换DFT/离散傅里叶反变换IDFT
  12. android+otg+apk,android手机 OTG功能调试usb串口的demo程序
  13. 停课不停学致家长的一封信
  14. 如何优雅的美化kali,实现双桌面环境
  15. 爱快中的虚拟机不能获取IPV4地址
  16. R7 5800H 3060 ubuntu20 配置全纪录(一)主要包括:N卡驱动、网卡驱动、virtualenv、CUDA and pytorch
  17. 让米帝领事馆给你报空气质量(动态网页爬取及简单的数据整理)
  18. 部落战争手游源码( 服务端+客户端+资源+开发文档)
  19. 设备树学习(四、内核head.S对uboot传参的处理)
  20. 和平精英苹果系统显示服务器暂未开放,和平精英苹果更新不了 苹果无法进行版本更新如何解决...

热门文章

  1. 学python对学c++有帮助吗_2020,你该学习Python还是C++
  2. C/S架构和B/S架构介绍
  3. xampp python linux,Ubuntu的XAMPP着运行python脚本
  4. android edittext html 图片,Android EditText加载HTML内容(内容包含网络图片) -电脑资料...
  5. 车模厂商能否用点心?
  6. 第十七届全国大学智能车竞赛STC芯片申请方法
  7. 2021年春季学期-信号与系统-第五次作业参考答案
  8. 第十五届全国大学生智能汽车竞赛青少年组获奖名单
  9. 如何配置Keil 外部编辑器?
  10. 如何使用Python语言将测量数据曲线动起来? matplotlib转换成 GIF文件