2018年5月29日

基于Spring aop写的一个简单的耗时监控

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

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

1
2
3
4
5
...
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上下文(切记)。

posted @ 2018-05-29 21:39 NewPanderKing 阅读(930) 评论(0) 推荐(2)

2015年10月18日

设计模式之建造者模式

摘要: 意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 适用性:当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。 当构造过程必须允许被构造的对象有不同的表示时。 建造者模式通常包括以下这几个角色: 1、Builder:给出一个抽象接口,规范建造者对于生产 阅读全文

posted @ 2015-10-18 17:02 NewPanderKing 阅读(328) 评论(1) 推荐(1)

设计模式之工厂模式

摘要: 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。工厂模式可以分为三类:1)简单工厂模式(Simple Factory)2)工厂方法模式(Factory Method)3)抽象工厂模式(Abstract Factory)这三种模式从上到下逐步抽象,并且... 阅读全文

posted @ 2015-10-18 15:51 NewPanderKing 阅读(424) 评论(0) 推荐(0)

2015年10月17日

IDE神器intellij idea的基本使用

摘要: 一、关于新建工程,导入工程,配置jdk,tomcat这里不做过多的讲述,必定网络上关于此类配置一堆一堆的。二、编码快捷键(比较常用的快捷键)该套快捷键选择的是:Mac OS X 10.5+1、 alt+F7 非常非常频繁使用的一个快捷键,可以帮你找 到你的函数或者变量或者类的所有引用到的地... 阅读全文

posted @ 2015-10-17 18:51 NewPanderKing 阅读(43868) 评论(7) 推荐(2)

2015年4月13日

[js] js判断浏览器(转)

摘要: (function($, window, document,undefined){ if(!window.browser){ var userAgent = navigator.userAgent.toLowerCase(),uaMatch; ... 阅读全文

posted @ 2015-04-13 10:32 NewPanderKing 阅读(317) 评论(0) 推荐(0)

2015年4月2日

java知识大全积累篇

摘要: 原文出自:http://www.importnew.com/14429.html构建这里搜集了用来构建应用程序的工具。Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建。Maven优于Apache Ant。后者采用了一种过程化的方式进行配置,所以维护... 阅读全文

posted @ 2015-04-02 12:10 NewPanderKing 阅读(3290) 评论(0) 推荐(2)

2015年3月25日

一些技术大牛的博客集锦(转)

摘要: 原文出自git:https://github.com/Vigorass/ITBlogs由于校园网进不去git,这里给大家复制一份仅供参考。技术博客网站推荐这里收集技术博客和网站,欢迎大家fork和pull requests综合伯乐在线博客是一个IT互联网职业社区。为IT互联网行业的企业和个人提供服务... 阅读全文

posted @ 2015-03-25 16:57 NewPanderKing 阅读(16034) 评论(2) 推荐(2)

2015年3月23日

添加鼠标右击菜单

摘要: 1、添加文件夹右击菜单a) 打开注册表: win+R 输入 regedit命令。进入注册表页面。b) 在注册表页面找到 HKEY_CLASSES_ROOT----->Directory----->shellc)在shell上点右键,然后在弹出菜单中选择“新建”----->“项”,建立一个名为“ope... 阅读全文

posted @ 2015-03-23 11:21 NewPanderKing 阅读(491) 评论(0) 推荐(0)

2015年1月3日

java 方法调用绑定

摘要: 将一个方法调用同一个方法主体关联起来被称作绑定。若在程序执行前进行绑定(由编译器和连接器实现),叫做前期绑定。读者可能从来没有听说过这个术语,因为它在面向过程语言中不需要选择就默认的绑定方式。例如C语言有一种方法调用,那就是前期绑定。后期绑定也叫做动态绑定或是运行时绑定,它的含义是在运行时根据对象的... 阅读全文

posted @ 2015-01-03 10:31 NewPanderKing 阅读(1493) 评论(0) 推荐(0)

2014年12月1日

sublime Text 几款插件

摘要: 留着自已以后用:http://blog.csdn.net/nivana999/article/details/78238051、sublime text实现vim命令格式(Vintage插件是自带的插件,默认是忽略掉的)选择,setting user下,添加一条命令:"ignored_package... 阅读全文

posted @ 2014-12-01 21:23 NewPanderKing 阅读(10385) 评论(0) 推荐(0)

< 2025年7月 >
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9

导航

点击右上角即可分享
微信分享提示