So you want both butter and jam. Okay. I will help you use loading cache along with keeping caching logic separate.
Consider you have a service class SampleServiceImpl
which implements SampleService
interface.
Service interface:
public interface SampleService {
User getUser(int id);
}
Service Implementation:
@Service
public class SampleServiceImpl implements SampleService {
public User getUser(int id) {
// fetch user from database
return user;
}
}
Create one more class SampleServiceCache
public class SampleServiceCache extends ServiceCacheImpl {
@Autowired
public SampleServiceCache(int expiryTime, int maximumSize) {
loadingCache =
CacheBuilder.newBuilder().maximumSize(maximumSize).expireAfterAccess(expiryTime, TimeUnit.HOURS).build(
new CacheLoader<Integer, User>() {
@Override
public User load(@Nonnull Integer userId) {
return SampleServiceCache.super.getUser(userId);
}
});
}
@Override
public User getUser(int userId) {
return loadingCache.getUnchecked(userId);
}
}
In you bean config:
@Bean
public SampleService sampleService() {
return new SampleServiceCache(expiry, maxSize);
}
The day you want to remove cache, you have to do two things:
1. Remove the cache class.
2. Change bean config to return actual implementation object rather than cache implementation object.
P.S. You can define multiple loading caches for different behaviors say user retrieval, article retrieval, etc.