Caching is key for performance of nearly every application. Distributed caching is sometimes needed, but not always. In many cases a local cache would work just fine and there’s no need for the overhead and complexity of the distributed cache.
So, in many applications, including plain Spring and Spring Boot, you can use
@Cacheable on any method and its result will be cached so that the next time the method is invoked, the cached result is returned.
Spring has some default cache manager implementations, but external libraries are always better and more flexible than simple implementations. Caffeine, for example is a high-performance Java cache library. And Spring Boot comes with a
CaffeineCacheManager. So, ideally, that’s all you need – you just create a cache manager bean and you have caching for your
However, the provided cache manager allows you to configure just one cache specification. Cache specifications include the expiry time, initial capacity, max size, etc. So all of your caches under this cache manager will be created with a single cache spec. The cache manager supports a list of predefined caches as well as dynamically created caches, but on both cases a single cache spec is used. And that’s rarely useful for production. Built-in cache managers are something you have to be careful with, as a general rule.
There are a few blogposts that tell you how to define custom caches with custom specs. However, these options do not support the dynamic, default cache spec usecase that the built-in manager supports. Ideally, you should be able to use any name in
@Cacheable and automatically a cache should be created with some default spec, but you should also have the option to override that for specific caches.
That’s why I decided to use a simpler approach than defining all caches in code that allows for greater flexibility. It extends the
CaffeineCacheManager to provide that functionality:
In short, it create one caffeine builder per spec and uses that instead of the default builder when a new cache is needed.
Then a sample XML configuration would look like this:
With Java config it’s pretty straightforward – you just set the
While Spring has already turned into a huge framework that provides all kinds of features, it hasn’t abandoned the design principles of extensibility.
Extending built-in framework classes is something that happens quite often, and it should be in everyone’s toolbox. These classes are created with extension in mind – you’ll notice that many methods in the
protected. So we should make use of that whenever needed.