Un guide pour la mise en cache au printemps

Un guide pour la mise en cache au printemps

1. L'abstraction du cache?

Dans cet article, nous allons vous montrer commentuse the Caching Abstraction in Spring - et généralement, améliorer les performances de votre système.

Nous allons activer la mise en cache simple pour certains exemples de méthodes du monde réel et nous expliquerons comment nous pouvons pratiquement améliorer les performances de ces appels grâce à une gestion intelligente du cache.

Lectures complémentaires:

Exemple de démarrage de printemps Ehcache

Un guide rapide et pratique sur l'utilisation de Spring avec Ehcache.

Read more

Expulsion de cache lors du démarrage du printemps

Apprenez à invalider des caches avec Spring Boot.

Read more

2. Commencer

L'abstraction principale de mise en cache fournie par Spring réside dans le smodulespring-context . Ainsi, lors de l'utilisation de Maven, nospom.xml doivent contenir la dépendance suivante:


    org.springframework
    spring-context
    5.1.8.RELEASE

Fait intéressant, il existe un autre module nomméspring-context-support, qui se trouve au-dessus du smodulespring-context et fournit quelquesCacheManagers upplémentaires soutenus par desEhCache ouCaffeine. Si vous comptez les utiliser comme stockage de cache, utilisez plutôt le smodulespring-context-support :


    org.springframework
    spring-context-support
    5.1.8.RELEASE

Puisque le modulespring-context-support dépend de manière transitoire du smodulespring-context , il n'est pas nécessaire de faire une déclaration de dépendance distincte pour lesspring-context.

2.1. Botte de printemps

Si vous êtes un utilisateur de Spring Boot, utilisez le package sstarterspring-boot-starter-cache pour ajouter facilement les dépendances de mise en cache:


    org.springframework.boot
    spring-boot-starter-cache

Sous le capot, le démarreur apporte le smodulespring-context-support .

3. Activer la mise en cache

Pour activer la mise en cache, Spring utilise bien les annotations, un peu comme si vous activiez toute autre fonctionnalité de niveau de configuration dans la structure.

La fonction de mise en cache peut être activée de manière déclarative en ajoutant simplement l'annotation@EnableCaching à l'une des classes de configuration:

@Configuration
@EnableCaching
public class CachingConfig {

    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("addresses");
    }
}

Vous pouvez, bien sûr, la configuration deenable cache management with XML également:


    

    
        
            
                
            
        
    

Note: Après avoir activé la mise en cache - pour la configuration minimale - nousmust enregistrons uncacheManager.

Using XML does enable more flexible options pour configurer la mise en cache - vous pouvez spécifier votre propre Cache-Manager, Cache-Resolver, Error-Handler et généralement, utiliser des options de personnalisation plus avancées (refer to the Javadoc pour plus de détails).

3.1. Botte de printemps

Lors de l'utilisation de Spring Boot, la simple présence du package de démarrage sur le chemin de classe à côté de l'annotationEnableCaching enregistrerait le mêmeConcurrentMapCacheManager.  Donc, il n'y a pas besoin d'une déclaration de bean séparée.

De plus, nous pouvons personnaliser leauto-configuredCacheManager en utilisant un ou plusieurs sbeansCacheManagerCustomizer<T> :

@Component
public class SimpleCacheCustomizer
  implements CacheManagerCustomizer {

    @Override
    public void customize(ConcurrentMapCacheManager cacheManager) {
        cacheManager.setCacheNames(asList("users", "transactions"));
    }
}

Le sauto-configurationCacheAutoConfiguration récupère ces personnalisateurs et les applique auCacheManager  actuel avant son initialisation complète.

4. Utiliser la mise en cache avec des annotations

Une fois que vous avez activé la mise en cache, l'étape suivante consiste à lier le comportement de mise en cache aux méthodes avec des annotations déclaratives.

4.1. àCacheable

Le moyen le plus simple d'activer le comportement de mise en cache pour une méthode est de la délimiter avec@Cacheable et de le paramétrer avec le nom du cache où les résultats seraient stockés:

@Cacheable("addresses")
public String getAddress(Customer customer) {...}

L'appel degetAddress() vérifiera d'abord le cacheaddresses avant d'appeler réellement la méthode, puis de mettre en cache le résultat.

Alors que dans la plupart des cas, un seul cache suffit, la structure Spring prend également en charge la transmission de plusieurs caches en tant que paramètres:

@Cacheable({"addresses", "directory"})
public String getAddress(Customer customer) {...}

____Dans ce cas, si l'un des caches contient le résultat requis, le résultat est renvoyé et la méthode n'est pas appelée.

4.2. àCacheEvict __

Maintenant, quel serait le problème avec toutes les méthodes@Cacheable?

Le problème est la taille -we don’t want to populate the cache with values that we don’t need often. Les caches peuvent devenir assez volumineux, assez rapidement et nous pourrions conserver beaucoup de données périmées ou inutilisées.

L'annotation@CacheEvict est utilisée pour indiquer la suppression d'une ou plusieurs / toutes les valeurs - afin que les nouvelles valeurs puissent être chargées à nouveau dans le cache:

@CacheEvict(value="addresses", allEntries=true)
public String getAddress(Customer customer) {...}

Ici, nous utilisons le paramètre supplémentaireallEntries en conjonction avec le cache à vider - pour effacer toutes les entrées du cacheaddresses et le préparer aux nouvelles données.

__ 4.3. àCachePut

Alors que@CacheEvict réduit la surcharge de recherche d'entrées dans un grand cache en supprimant les entrées obsolètes et inutilisées, idéalement, vous voulezavoid evicting too much data out of the cache.

Au lieu de cela, vous souhaitez mettre à jour de manière sélective et intelligente les entrées chaque fois qu'elles sont modifiées.

Avec l'annotation@CachePut, vous pouvez mettre à jour le contenu du cache sans interférer avec l'exécution de la méthode. C'est-à-dire que la méthode serait toujours exécutée et le résultat mis en cache.

@CachePut(value="addresses")
public String getAddress(Customer customer) {...}

La différence entre@Cacheable et@CachePut est que@Cacheable vaskip running the method, tandis que@CachePut vaactually run the method puis met ses résultats dans le cache.

4.4. àCaching

Que faire si vous souhaitez utiliser plusieurs annotations du même type pour la mise en cache d'une méthode. Regardez l'exemple incorrect ci-dessous:

@CacheEvict("addresses")
@CacheEvict(value="directory", key=customer.name)
public String getAddress(Customer customer) {...}

La compilation du code ci-dessus échouera, car Java n'autorise pas la déclaration de plusieurs annotations du même type pour une méthode donnée.

La solution de contournement au problème ci-dessus serait la suivante:

@Caching(evict = {
  @CacheEvict("addresses"),
  @CacheEvict(value="directory", key="#customer.name") })
public String getAddress(Customer customer) {...}

Comme indiqué dans l'extrait de code ci-dessus, vous pouvezgroup multiple caching annotations avec@Caching et l'utiliser pour implémenter votre propre logique de mise en cache personnalisée.

4.5. àCacheConfig

Avec l'annotation@CacheConfig, vous pouvezstreamline some of the cache configuration into a single place – at the class level - pour ne pas avoir à déclarer des choses plusieurs fois:

@CacheConfig(cacheNames={"addresses"})
public class CustomerDataService {

    @Cacheable
    public String getAddress(Customer customer) {...}

5. Mise en cache conditionnelle

Parfois, la mise en cache peut ne pas fonctionner correctement pour une méthode dans toutes les situations.

Par exemple - en réutilisant notre exemple à partir de l'annotation@CachePut - cela exécutera à la fois la méthode et mettra en cache les résultats à chaque fois:

@CachePut(value="addresses")
public String getAddress(Customer customer) {...}

5.1. Paramètre de condition

Maintenant, si nous voulons plus de contrôle sur le moment où l'annotation est active,@CachePut peut être paramétré avec un paramètre de condition qui prend une expression SpEL pour garantir que les résultats sont mis en cache en fonction de l'évaluation de cette expression:

@CachePut(value="addresses", condition="#customer.name=='Tom'")
public String getAddress(Customer customer) {...}

5.2. Sauf paramètre

Nous pouvons également contrôler la mise en cachebased on the output of the method rather than the input - via le paramètreunless:

@CachePut(value="addresses", unless="#result.length()<64")
public String getAddress(Customer customer) {...}

L'annotation ci-dessus mettrait en cache les adresses, à moins qu'elles ne soient inférieures à 64 caractères.

Il est important de savoir que les paramètrescondition etunless peuvent être utilisés conjointement avec toutes les annotations de mise en cache.

Ce type de mise en cache conditionnelle peut s'avérer très utile pour gérer des résultats volumineux et personnaliser le comportement en fonction de paramètres d'entrée au lieu d'appliquer un comportement générique à toutes les opérations.

6. Mise en cache déclarative basée sur XML

Si vous n’avez pas accès au code source de votre application ou si vous souhaitez injecter le comportement de mise en cache en externe, vous pouvez également utiliser la mise en cache déclarative basée sur XML.

Voici notre configuration XML: