
Configuration d'un gestionnaire de cache (`CacheManager`)
Apprenez à configurer et personnaliser le CacheManager dans Spring Boot pour différents fournisseurs de cache (Caffeine, Redis, EhCache...) et à définir des options de cache spécifiques.
Le rôle central du CacheManager
Dans l'abstraction de cache de Spring, le org.springframework.cache.CacheManager est l'interface pivot. Il sert de pont entre l'infrastructure de mise en cache de Spring (activée par @EnableCaching et utilisant des annotations comme @Cacheable) et l'implémentation de cache concrète que vous avez choisie (Caffeine, EhCache, Redis, Hazelcast, une simple Map, etc.).
Le rôle principal du CacheManager est de fournir des instances de org.springframework.cache.Cache sur demande. Chaque instance de Cache représente un cache nommé (par exemple, "produits", "utilisateurs") et expose les opérations de base nécessaires : récupérer une valeur par clé (get), ajouter ou mettre à jour une valeur (put), et supprimer une valeur (evict). Les proxies AOP de Spring utilisent le CacheManager pour obtenir le Cache approprié (basé sur le nom spécifié dans l'annotation) et interagissent ensuite avec cet objet Cache pour appliquer la logique de mise en cache.
Pour que l'abstraction de cache de Spring fonctionne, il est donc indispensable qu'au moins un bean de type CacheManager soit défini et disponible dans le contexte d'application Spring.
L'auto-configuration de Spring Boot : la magie par défaut
Heureusement, Spring Boot simplifie grandement la configuration du CacheManager grâce à son mécanisme d'auto-configuration. Si vous avez activé le caching (@EnableCaching) et ajouté une dépendance vers un fournisseur de cache supporté dans votre projet, Spring Boot tentera de configurer automatiquement un CacheManager pour vous.
L'ordre de détection et de préférence est généralement le suivant (peut légèrement varier selon la version de Spring Boot) :
- JCache (si
javax.cache.CachingProviderest présent et configuré) - Caffeine (si
com.github.ben-manes.caffeine:caffeineest présent) - EhCache 2.x (si
net.sf.ehcache:ehcacheest présent et un fichierehcache.xmlest trouvé) - Hazelcast (si
com.hazelcast:hazelcastest présent et configuré) - Infinispan (si
org.infinispan:infinispan-spring-boot-starter-cacheest présent) - Couchbase (si
com.couchbase.client:java-clientetspring-boot-starter-data-couchbasesont présents) - Redis (si
org.springframework.boot:spring-boot-starter-data-redisest présent) - Cache générique (si aucun des précédents n'est trouvé)
- Simple (basé sur
ConcurrentHashMap, comme dernier recours sispring-boot-starter-cacheest présent mais aucune autre implémentation)
Par exemple, si vous ajoutez spring-boot-starter-cache et la dépendance Caffeine à votre `pom.xml`, Spring Boot auto-configurera un CaffeineCacheManager sans que vous ayez à écrire de code de configuration Java spécifique. Les caches seront créés dynamiquement à la volée lorsqu'ils seront référencés pour la première fois dans une annotation (@Cacheable("monNouveauCache")), avec des paramètres par défaut.
Vous pouvez influencer légèrement l'auto-configuration via des propriétés dans application.properties/yml, notamment pour spécifier les noms des caches à pré-créer (spring.cache.cache-names) ou pour choisir explicitement le type de cache à utiliser si plusieurs fournisseurs sont présents (spring.cache.type=redis).
Personnalisation via les propriétés (exemple Redis)
Pour certains fournisseurs, l'auto-configuration peut être affinée via des propriétés spécifiques. Un bon exemple est Redis. Lorsque spring-boot-starter-data-redis est présent, un RedisCacheManager est auto-configuré. Vous pouvez personnaliser le comportement de ce cache via des propriétés spring.cache.redis.*.
Exemple de configuration dans application.properties pour Redis :
# Activer le cache Redis (souvent implicite si dépendance présente)
spring.cache.type=redis
# Durée de vie (Time To Live - TTL) par défaut pour toutes les entrées du cache
spring.cache.redis.time-to-live=60000 # 60 secondes (en millisecondes)
# Préfixe optionnel pour les clés de cache dans Redis
spring.cache.redis.key-prefix=monapp::cache::
# Utiliser le préfixe de clé (true par défaut)
spring.cache.redis.use-key-prefix=true
# Autoriser ou non le stockage de valeurs nulles (false par défaut)
spring.cache.redis.cache-null-values=true
# Configuration de la connexion Redis elle-même (si différente des valeurs par défaut localhost:6379)
spring.redis.host=redis.example.com
spring.redis.port=6379
# spring.redis.password=...
Ces propriétés permettent un contrôle de base sur le comportement du cache Redis sans nécessiter de configuration Java. Cependant, pour des personnalisations plus avancées (TTL différents par cache, configuration de la sérialisation, etc.), une configuration Java explicite sera nécessaire.
Configuration Java explicite du CacheManager
Lorsque l'auto-configuration ne suffit pas ou que vous souhaitez un contrôle total, vous pouvez définir votre propre bean CacheManager dans une classe de configuration @Configuration.
Exemple avec Caffeine (pour définir des spécifications de cache) :
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableCaching
public class CustomCacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("utilisateurs", "produits");
// Configuration par défaut pour les caches créés dynamiquement
// cacheManager.setCaffeine(caffeineCacheBuilder());
// Configuration spécifique pour le cache "utilisateurs"
cacheManager.registerCustomCache("utilisateurs",
Caffeine.newBuilder()
.maximumSize(100)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build());
// Configuration spécifique pour le cache "produits"
cacheManager.registerCustomCache("produits",
Caffeine.newBuilder()
.maximumSize(500)
.expireAfterAccess(30, TimeUnit.MINUTES)
.weakKeys() // Exemple d'option spécifique Caffeine
.build());
// Si vous voulez permettre la création dynamique d'autres caches avec des réglages par défaut
// cacheManager.setCacheSpecification("maximumSize=200,expireAfterWrite=5m"); // Alternative via String spec
return cacheManager;
}
// Helper pour la config par défaut (si nécessaire)
// CaffeineDans cet exemple, nous créons explicitement un CaffeineCacheManager, enregistrons deux caches nommés ("utilisateurs", "produits") avec des configurations Caffeine spécifiques (taille maximale, politique d'expiration différente).
Exemple avec Redis (pour définir des TTL par cache et configurer la sérialisation) :
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;
import java.time.Duration;
@Configuration
@EnableCaching
public class CustomRedisCacheConfig {
// Configuration de sérialisation JSON (à utiliser pour les valeurs)
private final SerializationPairCette approche avec RedisCacheManagerBuilderCustomizer est souvent préférée car elle permet de bénéficier de l'auto-configuration de la RedisConnectionFactory tout en personnalisant finement les aspects du cache (TTL, sérialisation par cache).
Gestion de plusieurs CacheManagers
Dans certains cas avancés, vous pourriez avoir besoin d'utiliser plusieurs fournisseurs de cache simultanément (par exemple, un cache en mémoire rapide pour certaines données et Redis pour d'autres). Spring permet de définir plusieurs beans CacheManager.
Cependant, si plusieurs CacheManager existent, Spring ne sait pas lequel utiliser par défaut. Vous devez alors explicitement désigner l'un d'eux comme étant le principal avec l'annotation @Primary sur sa définition de bean.
Pour utiliser un CacheManager non primaire avec les annotations de cache, vous devez spécifier son nom de bean dans l'attribut cacheManager de l'annotation :
@Service
public class MonService {
// Utilisera le CacheManager @Primary par défaut
@Cacheable("cachePrimaire")
public String methodeCacheePrimaire(String id) {
// ...
return "donnees primaires";
}
// Spécifie explicitement d'utiliser le CacheManager nommé "redisCacheManager"
@Cacheable(value = "cacheSecondaire", cacheManager = "redisCacheManager")
public String methodeCacheeSecondaire(String id) {
// ...
return "donnees secondaires";
}
}
Cela nécessite que vous ayez défini des beans CacheManager avec les noms correspondants (par exemple, via @Bean(name = "redisCacheManager")).
Conclusion : Maîtriser le CacheManager pour un caching efficace
Le CacheManager est le coeur de l'abstraction de cache de Spring. Bien que Spring Boot fasse un excellent travail d'auto-configuration dans la plupart des cas, comprendre le rôle du CacheManager et savoir comment le personnaliser est essentiel pour optimiser la stratégie de mise en cache de votre application.
Que ce soit via les propriétés de configuration pour des ajustements simples ou via une configuration Java explicite pour un contrôle fin (définition des caches nommés, TTL spécifiques, politiques d'éviction, sérialisation), la maîtrise du CacheManager vous permet d'adapter précisément le comportement du cache à vos besoins, garantissant ainsi des gains de performance optimaux tout en maintenant la clarté de votre code métier grâce à l'approche déclarative de Spring.