Spring Cache @Cacheable - not working while calling from another method of the same bean Spring Cache @Cacheable - not working while calling from another method of the same bean java java

Spring Cache @Cacheable - not working while calling from another method of the same bean


I believe this is how it works. From what I remember reading, there is a proxy class generated that intercepts all requests and responds with the cached value, but 'internal' calls within the same class will not get the cached value.

From https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable

Only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual cache interception at runtime even if the invoked method is marked with @Cacheable.


Since Spring 4.3 the problem could be solved using self-autowiring over @Resource annotation:

@Component@CacheConfig(cacheNames = "SphereClientFactoryCache")public class CacheableSphereClientFactoryImpl implements SphereClientFactory {    /**     * 1. Self-autowired reference to proxified bean of this class.     */    @Resource    private SphereClientFactory self;    @Override    @Cacheable(sync = true)    public SphereClient createSphereClient(@Nonnull TenantConfig tenantConfig) {        // 2. call cached method using self-bean        return self.createSphereClient(tenantConfig.getSphereClientConfig());    }    @Override    @Cacheable(sync = true)    public SphereClient createSphereClient(@Nonnull SphereClientConfig clientConfig) {        return CtpClientConfigurationUtils.createSphereClient(clientConfig);    }}


The example below is what I use to hit the proxy from within the same bean, it is similar to @mario-eis' solution, but I find it a bit more readable (maybe it's not:-). Anyway, I like to keep the @Cacheable annotations at the service level:

@Service@Transactional(readOnly=true)public class SettingServiceImpl implements SettingService {@Injectprivate SettingRepository settingRepository;@Injectprivate ApplicationContext applicationContext;@Override@Cacheable("settingsCache")public String findValue(String name) {    Setting setting = settingRepository.findOne(name);    if(setting == null){        return null;    }    return setting.getValue();}@Overridepublic Boolean findBoolean(String name) {    String value = getSpringProxy().findValue(name);    if (value == null) {        return null;    }    return Boolean.valueOf(value);}/** * Use proxy to hit cache  */private SettingService getSpringProxy() {    return applicationContext.getBean(SettingService.class);}...

See also Starting new transaction in Spring bean