前言:毕业后应该有一两年没有好好的更新博客了,回头看看自己这一年,似乎少了太多的沉淀了。让自己做一个爱分享的人,好的知识点拿出来和大家一起分享,一起学习。

背景: 在做项目的时候,大家肯定都遇到对一些对方法,模块耗时的监控,为了方便性能的监控,问题的定位等。如果每一个方法里都加上

...
Stopwatch watch = Stopwatch.createStarted();
...
watch.elapsed(TimeUnit.MILLISECONDS)
...

 类似的代码肯定没问题,但是就会显得代码特别的冗余。正好近期看了点spring-aop的相关数据,就想到做一个对方法的切面监控方法耗时,同时利用一个简单的注解,可以达到代码简洁化。

1、定义注解类

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PerfMonitor { /**
* 基本描述,可不设置,默认为空
* @return
*/
String desc() default "";
}

2、定义切面

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit; import com.google.common.base.Stopwatch;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature; public class PerfAspect {

private Logger logger = Logger.getLogger(PerfAspect.class);
/**
* 耗时,spring线程问题,防止不同线程之间出现数据影响
*/
private ThreadLocal<Stopwatch> watch = new ThreadLocal<>(); /**
* 进入方法埋点
*/
public void before() {
// 设置进入时间
watch.set(Stopwatch.createStarted());
} /**
* 结束方法埋点
* @param point
*/
public void after(JoinPoint point) {
Class c = point.getTarget().getClass();
Signature signature = point.getSignature();
StringBuilder sb = new StringBuilder();
String desc = getAnnotationDesc(point);
if (desc != null && desc != "") {
sb.append(desc);
} else {
sb.append(c.getSimpleName()).append(".").append(signature.getName());
}
sb.append(",cost[").append(watch.get().elapsed(TimeUnit.MILLISECONDS)).append("]ms");
logger.info(sb.toString())
} /**
* 获取注解描述信息
* @param joinPoint
* @return
*/
private String getAnnotationDesc(JoinPoint joinPoint) {
Method method = getJoinPointMethod(joinPoint);
PerfMonitor perfMonitor = method.getAnnotation(PerfMonitor.class);
return perfMonitor.desc();
} /**
* 计算接入点监控方法
* @param joinPoint
* @return
*/
private Method getJoinPointMethod(JoinPoint joinPoint) {
Class c = joinPoint.getTarget().getClass();
Signature signature = joinPoint.getSignature();
if (c != null && c.getMethods() != null) {
for (Method method : c.getMethods()) {
if (method.getName() == signature.getName()) {
return method;
}
}
}
return null;
} }

3、在方法上打上该注解

public class Student implements Person {

    /**
* logger
*/
private Logger logger = Logger.getLogger(Student.class); @PerfMonitor(desc = "student eat perf")
public void eat(String food) {
  
logger.info("student eat " + food);
}
}
 

4、spring xml配置

    <bean id="student" class="com.common.util.test.Student"/>
<!--性能监控点-->
<bean id="perfAspect" class="com.common.util.perfmonitor.PerfAspect"/>
<!-- 开启aop -->
<aop:aspectj-autoproxy/>
<!-- aop配置 -->
<aop:config>
<!-- 连接点 -->
<aop:pointcut id="pointCut" expression="@annotation(com.common.util.perfmonitor.PerfMonitor)"/>
<aop:aspect ref="perfAspect">
<aop:after method="after" pointcut-ref="pointCut"/>
<aop:before method="before" pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>

5、测试入口

public class Client {

  public static void main(String[] args)  {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.aop.xml");
final Person person = (Person)ctx.getBean("student");
ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 100; i++) {
executorService.execute(new Runnable() {
public void run() { person.eat("fish");
}
}); }
}
}

ps:说明一下,该工具使用时,第1、2两步需要写入到底层common层代码中。如果是基于osgi的应用,不同的bundle之间spring上下文可能是不通的,那么需要在使用这个注解的bundle中配置步骤4中的spring上下文(切记)。

基于Spring aop写的一个简单的耗时监控的更多相关文章

  1. 只是一个用EF写的一个简单的分页方法而已

    只是一个用EF写的一个简单的分页方法而已 慢慢的写吧.比如,第一步,先把所有数据查询出来吧. //第一步. public IQueryable<UserInfo> LoadPagesFor ...

  2. spring boot: @Entity @Repository一个简单的数据读存储读取

    spring boot: @Entity @Repository一个简单的数据读存储读取 创建了一个实体类. 如何持久化呢?1.使用@Entity进行实体类的持久化操作,当JPA检测到我们的实体类当中 ...

  3. 写了一个简单的CGI Server

    之前看过一些开源程序的源码,也略微知道些Apache的CGI处理程序架构,于是用了一周时间,用C写了一个简单的CGI Server,代码算上头文件,一共1200行左右,难度中等偏上,小伙伴可以仔细看看 ...

  4. 自己写的一个简单PHP采集器

    自己写的一个简单PHP采集器 <?php //**************************************************************** $url = &q ...

  5. 写了一个简单可用的IOC

    根据<架构探险从零开始写javaweb框架>内容写的一个简单的 IOC 学习记录    只说明了主要的类,从上到下执行的流程,需要分清主次,无法每个类都说明,只是把整个主线流程说清楚,避免 ...

  6. 写了一个简单的 Mybatis

    写了一个简单的 Mybatis,取名 SimpleMybatis . 具备增删改查的基本功能,后续还要添加剩下的基本数据类型和Java集合类型的处理. 脑图中有完整的源码和测试的地址 http://n ...

  7. 基于File NIO写的一个文件新增内容监控器

    基于File NIO写的一个文件新增内容监控器 需求说明 监控一个文件,如果文件有新增内容,则在控制台打印出新增内容. 代码示例 FileMoniter文件监控器类 package com.black ...

  8. 基于Java Agent的premain方式实现方法耗时监控(转),为了找到结论执行:premain在jvm启动的时候执行,所有方法前,会执行MyAgent的premain方法

    Java Agent是依附于java应用程序并能对其字节码做相关更改的一项技术,它也是一个Jar包,但并不能独立运行,有点像寄生虫的感觉.当今的许多开源工具尤其是监控和诊断工具,很多都是基于Java ...

  9. Spring 学习——基于Spring WebSocket 和STOMP实现简单的聊天功能

    本篇主要讲解如何使用Spring websocket 和STOMP搭建一个简单的聊天功能项目,里面使用到的技术,如websocket和STOMP等会简单介绍,不会太深,如果对相关介绍不是很了解的,请自 ...

随机推荐

  1. 使用IntelliJ Idea新建SpringBoot项目

    简单给大家介绍一下我来创建SpringBoot项目使用的工具,本人使用IntelliJ Idea来创建项目,利用其中的Spring Initializr工具来快速创建项目. 步骤如下: 菜单栏中选择F ...

  2. 7种方法实现移动端Retina屏幕1px边框效果

    在Reina(视网膜)屏幕的手机上,使用CSS设置的1px的边框实际会比视觉稿粗很多.在之前的项目中,UI告诉我说我们移动项目中的边框全部都变粗了,UI把他的设计稿跟我的屏幕截图跟我看,居然真的不一样 ...

  3. position 属性的值的比较

    可取的四个值:static/relative/absolute/fixed static:默认值,top/right/bottom/left 无作用,z-index无效 relative:相对于原来的 ...

  4. CODEVS.5037.线段树练习4加强版(分块 区间k的倍数)

    题目链接 /* 如果用线段树,每个节点要再开k的空间,显然不行.但是分块可以(虽然空间依旧爆炸) 分块.用bloans[i][j]表示 第i块 模k为j 的有多少个 对于不是整块的,查询时应判断 A[ ...

  5. python高级——垃圾回收机制

    GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用.GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在 ...

  6. STM32——C语言课堂原代码

    指针 /* ============================================================================ Name : Hello.c Au ...

  7. oracle数据库启动和关闭方式

    Oracle数据库是重量级的,其管理非常复杂,将其在Linux平台上的启动和关闭步骤整理一下. 安装完毕oracle以后,需要创建oracle系统用户,并在/home/oracle下面的.bash_p ...

  8. Docker 常用命令(四)

    1. 查看容器中的进程信息: docker top 772d23 查看容器的详细信息: docker inspect 772d23 持续更新日志 docker logs -f 7732dx

  9. C# RabbitMQ优先级队列实战项目演练

    一.需求背景 当用户在商城上进行下单支付,针对客户等级的不同和订单金额的大小划分客户级别,需要优先处理给标识为大订单的客户发送一份订单邮件提醒.那么我们应用程序如何解决这样的需求场景呢?今天阿笨给大家 ...

  10. SharePoint 读取内容的插件之SharepointPlus

    前言 最近,一直在前端和SharePoint进行交互,然后,发现一个好用的插件,分享给大家. 首先,需要添加一个引用,如下图: 当然,我这里只是举个例子,亲们一定要去下载这个库,然后传到服务器或者文档 ...