1. 需求
背景
性能调优阶段,需要找出执行时间比较长的方法,针对这些方法进行调优。
2. 可行方案
一种是传统的在每个方法前后获取System.currentMis(),然后得到方法的执行时间。
这种方式的缺点是方法多会写很多耦合代码,而且不可重用,测试完需要删掉。
另一种使用AOP监控方法的前后点,监控方法的执行时间,比较优雅且无侵入。
可行的方案之一是使用
Around Advice, 环绕通知可在方法执行前后做一些操作。
AOP,面向切面编程,Aspect Oriented Programming,
可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
3. AOP
jar librarys requires:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.6</version> </dependency>
Spring配置:
<aop:aspectj-autoproxy proxy-target-class="true"/>
AOP实现类:
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.util.StopWatch; /** * Created by jzq1999 on 2017/4/19. * 通过aop拦截后执行具体操作 */ @Aspect @Component public class DaoTimeInterceptor { private final static String POINT = "execution (* com.tzx.*.po.springjdbc.dao.imp.*.*(..))"; @Pointcut(POINT) public void recordLog(){} @Around("recordLog()") public Object around(ProceedingJoinPoint pjp) throws Throwable{ StopWatch stopWatch = new StopWatch(); stopWatch.start(); Object obj = pjp.proceed(pjp.getArgs()); stopWatch.stop(); long cost = stopWatch.getTotalTimeMillis(); if(cost > 10) { MethodSignature signature = (MethodSignature) pjp.getSignature(); String methodName = signature.getDeclaringTypeName() + "." + signature.getName(); System.out.println("----------- 执行" + methodName + "方法, 用时: " + cost + "ms -----------"); } return obj; } }