Spring中注解处理的顺序(@Cacheable和@Timed)

Posted

技术标签:

【中文标题】Spring中注解处理的顺序(@Cacheable和@Timed)【英文标题】:Order of annotation processing in Spring (@Cacheable and @Timed) 【发布时间】:2020-02-29 12:10:31 【问题描述】:

我想用@Cacheable@Timed(来自千分尺)来注释我的方法。 但我希望 @Timed 仅在数据未计时的情况下应用。 有没有办法做到这一点,以正确的顺序放置注释是否足够 - 那将是什么顺序?

我的@Timed 也在使用TimedAspect,不确定这是否相关。

现在我这样做如下:

@Cacheable
@Timed
public String getValue(long id) 
    ...

我找不到任何可以讨论此问题的 @Cacheable 文档。

【问题讨论】:

【参考方案1】:

我也有同样的问题;这是我的代理方法的样子:

  @Cacheable(cacheNames = "myCache")
  @Timed("getFoo")
  public MyObject getFoo() 
    ...
  

我不确定,所以我添加了一些日志消息,我发现 Timed 方面仅在实际调用该方法时才被缓存未命中。我不确定这是因为 Spring 的代理尊重方法上注释的顺序,还是出于其他原因。但为了安全起见,我推出了自己的方面(因为 TimedAspect 无论如何都不适合我)并实现了 org.springframework.core.Ordered

  @Override
  public int getOrder() 
    // Ensures that the @Timed annotation is processed *after* any other proxied annotations on the
    // method (such as @Cacheable), so we only record the method call if it's actually called.
    return Ordered.LOWEST_PRECEDENCE;
  

【讨论】:

【参考方案2】:

这很棘手,因为您正在处理 Spring 围绕您的业务 bean 创建的 AOP 代理,所以我不确定您是否可以依赖注释的顺序。

我认为你有几个选择:

您可能希望重构代码以使用多种方法,一种标记为@Cacheable,另一种标记为@Timed。但是,我认为这对您不起作用,因为您需要多个 bean(对同一个 bean 的调用不会被 AOP 代理拦截)。因此,您需要两个 bean,一个充当外观,另一个执行您想要缓存和监控的实际 @Timed 昂贵调用。 另一种选择可能是扩展@Timed@Cacheable 并在两个接口中实现Orderable,然后在您的bean 中使用它们。我不完全确定这会奏效,因为这取决于如何拾取注释。沿着这条线的东西:Specifying the order of proxy creation in Spring

希望对你有帮助。

【讨论】:

Orderable 是个好主意,我会试试的。

以上是关于Spring中注解处理的顺序(@Cacheable和@Timed)的主要内容,如果未能解决你的问题,请参考以下文章

Spring 缓存——@Cacheable

Spring 缓存注解@Cacheable的用法

为啥Spring对@Cacheable注解方法的单次调用执行@Cacheable keyGenerator 2次

详解Spring缓存注解@Cacheable,@CachePut , @CacheEvict使用

Spring缓存注解@Cache,@CachePut , @CacheEvict,@CacheConfig使用

Spring Cacheable 注解不缓存null值