bug描述
为了方便观察方法优化前后的执行时间,我使用自定义注解,配合AOP和StopWatch用来计算执行时长,但是运行项目时出现了异常信息:Handler dispatch failed: java.lang.NoSuchMethodError: 'double org.springframework.util.StopWatch......'
我的代码如下,其中StopWatch使用的是org.springframework.util包下的类,报错信息却是找不到这个方法
自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CostTime {
}
切面类(这里贴的是修改后的代码)
@Aspect
@Slf4j
@Component
public class CostTimeAspect {
@Pointcut("@annotation(com.tomla.gomall.aop.annotations.CostTime)")
public void CostTime(){}
@Around("CostTime()")
public Object costTime(ProceedingJoinPoint point) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//执行切入点,获取返回值
Object proceed = point.proceed();
//方法名
String methodName = point.getSignature().getName();
//类名
String className = point.getSignature().getDeclaringTypeName();
//计算耗时
stopWatch.stop();
log.info("类:{},方法:{},执行耗时(毫秒):{}",className,methodName,stopWatch.getTotalTimeMillis());
return proceed;
}
}
在需要统计执行时长的方法上加注解@CostTime
@CostTime
@GetMapping("/detail/{skuId}")
public Result<SkuItemVo> getDetailBySkuId(@PathVariable("skuId") Long skuId){
return skuInfoService.getDetailBySkuId(skuId);
}
解决bug
- 网上查阅资料可知,引起这个问题有多种原因,包括
jdk版本不同,依赖了不同版本jar包等等。我突然意识到我所用的StopWatch是org.springframework.util包下的,这个包位于spring-core包下,而我把这个基于自定义注解的切面类写在了微服务的common模块下,在其他服务中使用了这个自定义注解。也就是说,我定义切面类与使用切面类的位置不同,而两者使用的spring-core依赖版本不同!common模块使用的是org.springframework:spring-core:6.1.1版本,而另一个服务使用的是org.springframework:spring-core:6.0.4版本,意味着编译与运行时所处的环境不同,造成了这个严重的bug。 - 解决办法一:由于common引入了
hutool工具包,而其他服务都用到了此工具,所以统一使用hutool中提供StopWatch工具类,这样就不会出现使用了不同jar包带来的NoSuchMethodError问题了。 - 解决方法二:将两个模块中的spring-core修改为同一版本,不过我更喜欢第一种解决办法。