The Spring Framework provides support for transparently adding caching to an application.
At its core, the abstraction applies caching to methods, reducing thus the number of
executions based on the information available in the cache. The caching logic is applied
transparently, without any interference to the invoker. Spring Boot auto-configures the
cache infrastructure as long as the caching support is enabled via the @EnableCaching
annotation.
Note | |
---|---|
Check the relevant section of the Spring Framework reference for more details. |
In a nutshell, adding caching to an operation of your service is as easy as adding the relevant annotation to its method:
import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Component; @Component public class MathService { @Cacheable("piDecimals") public int computePiDecimal(int i) { // ... } }
This example demonstrates the use of caching on a potentially costly operation. Before
invoking computePiDecimal
, the abstraction will look for an entry in the piDecimals
cache matching the i
argument. If an entry is found, the content in the cache is
immediately returned to the caller and the method is not invoked. Otherwise, the method is
invoked and the cache is updated before returning the value.
Note | |
---|---|
You can also use the standard JSR-107 (JCache) annotations (e.g. |
If you do not add any specific cache library, Spring Boot will auto-configure a
Simple provider that uses concurrent maps in
memory. When a cache is required (i.e. piDecimals
in the example above), this provider
will create it on-the-fly for you. The simple provider is not really recommended for
production usage, but it’s great for getting started and making sure that you understand
the features. When you have made up your mind about the cache provider to use, please make
sure to read its documentation to figure out how to configure the caches that your
application uses. Practically all providers require you to explicitly configure every
cache that you use in the application. Some offer a way to customize the default caches
defined by the spring.cache.cache-names
property.
Note | |
---|---|
If you are using the cache infrastructure with beans that are not interface-based,
make sure to enable the |
The cache abstraction does not provide an actual store and relies on abstraction
materialized by the org.springframework.cache.Cache
and
org.springframework.cache.CacheManager
interfaces.
If you haven’t defined a bean of type CacheManager
or a CacheResolver
named
cacheResolver
(see CachingConfigurer
), Spring Boot tries to detect the following
providers (in this order):
Tip | |
---|---|
It is also possible to force the cache provider to use via the |
Tip | |
---|---|
Use the |
If the CacheManager
is auto-configured by Spring Boot, you can further tune its
configuration before it is fully initialized by exposing a bean implementing the
CacheManagerCustomizer
interface. The following sets a flag to say that null
values should be passed down to the underlying map.
@Bean public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() { return new CacheManagerCustomizer<ConcurrentMapCacheManager>() { @Override public void customize(ConcurrentMapCacheManager cacheManager) { cacheManager.setAllowNullValues(false); } }; }
Note | |
---|---|
In the example above, an auto-configured |
Generic caching is used if the context defines at least one
org.springframework.cache.Cache
bean. A CacheManager
wrapping all beans of that type
is created.
JCache is bootstrapped via the presence of a javax.cache.spi.CachingProvider
on the
classpath (i.e. a JSR-107 compliant caching library) and the JCacheCacheManager
provided by the spring-boot-starter-cache
‘Starter’. There are various compliant
libraries out there and Spring Boot provides dependency management for Ehcache 3,
Hazelcast and Infinispan. Any other compliant library can be added as well.
It might happen that more than one provider is present, in which case the provider must be explicitly specified. Even if the JSR-107 standard does not enforce a standardized way to define the location of the configuration file, Spring Boot does its best to accommodate with implementation details.
# Only necessary if more than one provider is present spring.cache.jcache.provider=com.acme.MyCachingProvider spring.cache.jcache.config=classpath:acme.xml
Note | |
---|---|
Since a cache library may offer both a native implementation and JSR-107 support Spring Boot will prefer the JSR-107 support so that the same features are available if you switch to a different JSR-107 implementation. |
Tip | |
---|---|
Spring Boot has a general support for Hazelcast. If
a single |
There are several ways to customize the underlying javax.cache.cacheManager
:
spring.cache.cache-names
property. If a
custom javax.cache.configuration.Configuration
bean is defined, it is used to
customize them.org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer
beans are
invoked with the reference of the CacheManager
for full customization.Tip | |
---|---|
If a standard |
EhCache 2.x is used if a file named ehcache.xml
can be found at the root of the
classpath. If EhCache 2.x, the EhCacheCacheManager
provided by the
spring-boot-starter-cache
‘Starter’ and such file is present it is used to bootstrap
the cache manager. An alternate configuration file can be provided as well using:
spring.cache.ehcache.config=classpath:config/another-config.xml
Spring Boot has a general support for Hazelcast. If
a HazelcastInstance
has been auto-configured, it is automatically wrapped in a
CacheManager
.
Infinispan has no default configuration file location so it must be specified explicitly (or the default bootstrap is used).
spring.cache.infinispan.config=infinispan.xml
Caches can be created on startup via the spring.cache.cache-names
property. If a custom
ConfigurationBuilder
bean is defined, it is used to customize them.
Note | |
---|---|
The support of Infinispan in Spring Boot is restricted to the embedded mode and is quite basic. If you want more options you should use the official Infinispan Spring Boot starter instead, check the documentation for more details. |
If the Couchbase java client and the couchbase-spring-cache
implementation are
available and Couchbase is configured, a
CouchbaseCacheManager
will be auto-configured. It is also possible to create additional
caches on startup using the spring.cache.cache-names
property. These will operate on
the Bucket
that was auto-configured. You can also create additional caches on another
Bucket
using the customizer: assume you need two caches on the "main" Bucket
(foo
and bar
) and one biz
cache with a custom time to live of 2sec on the another
Bucket
. First, you can create the two first caches simply via configuration:
spring.cache.cache-names=foo,bar
Then define this extra @Configuration
to configure the extra Bucket
and the biz
cache:
@Configuration public class CouchbaseCacheConfiguration { private final Cluster cluster; public CouchbaseCacheConfiguration(Cluster cluster) { this.cluster = cluster; } @Bean public Bucket anotherBucket() { return this.cluster.openBucket("another", "secret"); } @Bean public CacheManagerCustomizer<CouchbaseCacheManager> cacheManagerCustomizer() { return c -> { c.prepareCache("biz", CacheBuilder.newInstance(anotherBucket()) .withExpiration(2)); }; } }
This sample configuration reuses the Cluster
that was created via auto-configuration.
If Redis is available and configured, the RedisCacheManager
is auto-configured. It is
also possible to create additional caches on startup using the spring.cache.cache-names
property.
Note | |
---|---|
By default, a key prefix is added to prevent that if two separate caches use the same
key, Redis would have overlapping keys and be likely to return invalid values. We strongly
recommend to keep this setting enabled if you create your own |
Caffeine is a Java 8 rewrite of Guava’s cache and will supersede the Guava support in
Spring Boot 2.0. If Caffeine is present, a CaffeineCacheManager
(provided by the
spring-boot-starter-cache
‘Starter’) is auto-configured. Caches can be created on
startup using the spring.cache.cache-names
property and customized by one of the
following (in this order):
spring.cache.caffeine.spec
com.github.benmanes.caffeine.cache.CaffeineSpec
bean is definedcom.github.benmanes.caffeine.cache.Caffeine
bean is definedFor instance, the following configuration creates a foo
and bar
caches with a maximum
size of 500 and a time to live of 10 minutes
spring.cache.cache-names=foo,bar spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
Besides, if a com.github.benmanes.caffeine.cache.CacheLoader
bean is defined, it is
automatically associated to the CaffeineCacheManager
. Since the CacheLoader
is
going to be associated to all caches managed by the cache manager, it must be defined
as CacheLoader<Object, Object>
. Any other generic type will be ignored by the
auto-configuration.
If Guava is present, a GuavaCacheManager
is auto-configured. Caches can be created
on startup using the spring.cache.cache-names
property and customized by one of the
following (in this order):
spring.cache.guava.spec
com.google.common.cache.CacheBuilderSpec
bean is definedcom.google.common.cache.CacheBuilder
bean is definedFor instance, the following configuration creates a foo
and bar
caches with a maximum
size of 500 and a time to live of 10 minutes
spring.cache.cache-names=foo,bar spring.cache.guava.spec=maximumSize=500,expireAfterAccess=600s
Besides, if a com.google.common.cache.CacheLoader
bean is defined, it is automatically
associated to the GuavaCacheManager
. Since the CacheLoader
is going to be associated
to all caches managed by the cache manager, it must be defined as
CacheLoader<Object, Object>
. Any other generic type will be ignored by the
auto-configuration.
If none of the other providers can be found, a simple implementation using a
ConcurrentHashMap
as cache store is configured. This is the default if no caching
library is present in your application. Caches are created on-the-fly by default but you
can restrict the list of available caches using the cache-names
property. For instance,
if you want only foo
and bar
caches:
spring.cache.cache-names=foo,bar
If you do this and your application uses a cache not listed then it will fail at runtime when the cache is needed, but not on startup. This is similar to the way the "real" cache providers behave if you use an undeclared cache.