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);}...