简体   繁体   中英

Order of annotation processing in Spring (@Cacheable and @Timed)

I want to annotate my method with @Cacheable and also with @Timed (from micrometer). But I would like the @Timed to be applied only in case when the data is not timed. Is there a way to do that, is it enough to put the annotations in correct order - and which order would that be?

My @Timed is also using TimedAspect , not sure if that is relevant.

Right now I do it like below:

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

I couldn't find any documentation for @Cacheable that would discuss this.

This is tricky, since you are dealing with AOP proxies created by Spring around your business bean, so I am not sure whether you can rely on the order of the annotations.

I think that you have several options:

  • You might want to refactor your code to have several methods, one marked with @Cacheable and the other with @Timed . However, I think that this will not work with you since you need more than one bean (calls whitin the same bean are not intercepted by the AOP proxies). Therefore, you would need two beans, one acting as facade and the other doing the actual @Timed expensive call that you want to cache and monitor.
  • Another option might be to extend both @Timed and @Cacheable and implement Orderable in both interfaces, then use them in your bean. I am not totally sure that this will work, as it will depend on how the annotations are picked up. Something along this line: Specifying the order of proxy creation in Spring

Hope it helps.

I had this same exact issue; here's what my proxied method looks like:

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

I wasn't sure so I added some log messages, and what I found is that the Timed aspect is only getting hit for a cache miss, when the method is actually called. I'm not sure if that's because Spring's proxy respects the order of the annotations on the method, or for some other reason. But just to be safe, I rolled my own aspect (since TimedAspect wasn't working for me anyway) and implemented 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;
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM