如何记录 Spring Data JPA 存储库方法执行时间?

Posted

技术标签:

【中文标题】如何记录 Spring Data JPA 存储库方法执行时间?【英文标题】:How to log Spring Data JPA repository method execution time? 【发布时间】:2014-11-16 15:07:54 【问题描述】:

我有简单的 Spring Data JPA 存储库。

public interface UserRepository extends JpaRepository<UserEntity, Serializable> … 

有没有办法监控 Spring 生成的方法的执行时间(例如 findOne(…))?

【问题讨论】:

【参考方案1】:

最简单的方法是使用CustomizableTraceInterceptor,如下所示:

@Configuration
@EnableAspectJAutoProxy
public class SpringDataExecutionLoggingConfiguration 

  @Bean
  public CustomizableTraceInterceptor customizableTraceInterceptor() 

    CustomizableTraceInterceptor customizableTraceInterceptor = new CustomizableTraceInterceptor();
    customizableTraceInterceptor.setUseDynamicLogger(true);
    customizableTraceInterceptor.setExitMessage("Executed $[methodName] in $[invocationTime]");
    return customizableTraceInterceptor;
  

  @Bean
  public Advisor advisor() 

    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression("execution(public * org.springframework.data.repository.CrudRepository+.*(..))");
    return new DefaultPointcutAdvisor(pointcut, customizableTraceInterceptor());
  

【讨论】:

切入点不应该是:“execution(public * org.springframework.data.repository.Repository+.*(..))”? 它不起作用,我得到:java.lang.IllegalArgumentException:警告此类型名称不匹配:org.springframework.data.jpa.repository.CrudRepository [Xlint:invalidAbsoluteTypeName] 执行(public * org.springframework.data.repository.CrudRepository+.*(..))【参考方案2】:

另一个可行的解决方案:

@Aspect
@Component
public class ProfilerAspect 
    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Pointcut("execution(public * org.springframework.data.repository.Repository+.*(..))")
    public void monitor() 

    @Around("monitor()")
    public Object profile(ProceedingJoinPoint pjp) 
        long start = System.currentTimeMillis();
        logger.debug("JVM memory in use = "+ (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()));
        Object output = null;
        try 
            output = pjp.proceed();
         catch (Throwable e) 
            logger.error(e.getMessage(), e);
        
        long elapsedTime = System.currentTimeMillis() - start;
        logger.debug(pjp.getTarget()+"."+pjp.getSignature()+": Execution time: " + elapsedTime + " ms. ("+ elapsedTime/60000 + " minutes)");

        return output;
    

【讨论】:

这很酷,只是它会吞下异常并返回 null,这可能不是所需的行为。

以上是关于如何记录 Spring Data JPA 存储库方法执行时间?的主要内容,如果未能解决你的问题,请参考以下文章

使用spring data jpa删除数据库记录时出错

性能 - 使用 Spring JPA Data 搜索具有 2000 万条记录的表

Spring-data-jpa 学习笔记

如何在 Spring Boot 应用程序的同一个域类上同时使用 Spring Data JPA 和 Spring Data Elasticsearch 存储库?

Spring Data JPA调用存储过程实例

Spring Data Jpa如何实现审计和乐观锁功能