Skip to content
Advertisement

Accessing spring bean proxy reference itself

I have an issue with @Cacheable and @CacheEviction annotations. When I call these methods in the bean where they are declared, the aop part is not getting executed.

The underlying reason for this is that the bean access to its own instance itself, instead of accessing the spring proxy.

I have read this question where it is said that in most cases it should not be necessary a bean accessing the proxy.

Probably those answers work for me. The question is:

Is there any other way to make annotated methods work? Or does it sound like I found a good reason for a bean needing to access the proxy itself?

Answer

As is well documented in the Spring user manual, self-invocation cannot work with Spring AOP because Spring AOP uses proxies. So if you want to make self-invocation trigger an aspect, please switch to full AspectJ via LTW (load-time weaving). It works with the original beans and does not use any proxies.


Update: If you want to avoid using native AspectJ and instead as a (pretty lame and anti-AOP) workaround want to make your component proxy-aware, of course you can use self-injection and reference the cached method using the auto-wired proxy like this:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {
  @Autowired
  MyComponent myComponent;

  public void doSomething() {
    System.out.println(myComponent.doCacheable());
    System.out.println(myComponent.doCacheable());
    System.out.println(myComponent.doCacheable());
  }

  @Cacheable("myCache")
  public String doCacheable() {
    return "" + System.nanoTime();
  }
}

Calling doSomething() on the MyComponent bean should yield output like this:

247760543178800
247760543178800
247760543178800

This proves that caching works like this. If instead you just have three lines of either System.out.println(doCacheable()); or the weird, nonsensical variant from the other (now deleted) answer System.out.println(MyComponent.this.doCacheable());, then you would get three different values on the console, i.e. nothing would be cached.

Advertisement