web-dev-qa-db-fra.com

Comment avoir plusieurs configurations de gestionnaire de cache dans le cache de printemps java

Je veux avoir plusieurs gestionnaires de cache de printemps configurés dans mon application Web et je pourrais utiliser différents gestionnaires de cache à différents endroits de mon projet. Est-ce qu'il y a un moyen de faire ça.

21
Rekha

Vous pouvez procéder de plusieurs manières et la bonne réponse dépend de votre utilisation du cache.

Vous avez un gestionnaire de cache "principal"

Si vous utilisez CacheManager A pour 90% de votre cas d'utilisation et B pour 10%, je vous conseille de créer un CacheManager par défaut pour A (vous devrez le spécifier via une extension CacheConfigurerSupport ), quelque chose comme:

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {

    @Override
    @Bean // not strictly necessary
    public CacheManager cacheManager() { ... CacheManager A }

    @Bean
    public CacheManager bCacheManager() { ... CacheManager B }
}

Ensuite, pour le cas d'utilisation de 10%, vous ajoutez un CacheConfig en haut des classes qui doivent utiliser l'autre gestionnaire de cache

@CacheConfig(cacheManager="bCacheManager")
public class MyService { /*...*/ }

Si vous devez utiliser l'autre gestionnaire de cache pour une seule méthode, vous pouvez également le spécifier au niveau de la méthode

@Cacheable(cacheNames = "books", cacheManager = "bCacheManager")
public Book findById(long id) { /*...*/ }

Résolution plus fine

Si vous n'êtes pas dans cette situation, vous avez besoin d'un moyen de savoir quel gestionnaire de cache doit être utilisé au cas par cas. Vous pouvez le faire en fonction du type de cible (MyService) ou du nom du cache (books). Vous devrez implémenter un CacheResolver qui fera cette traduction pour vous.

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {

    @Override
    public CacheResolver cacheResolver() { ... }
}

Vérifiez le javadoc de CacheResolver pour plus de détails. Dans l'implémentation, vous pouvez avoir plusieurs instances CacheManager (en tant que bean ou non) que vous appellerez en interne en fonction de votre logique pour déterminer le gestionnaire à utiliser.

J'ai vu dans un commentaire que vous parliez de "module". La mise en cache est vraiment une question d'infrastructure, je vous conseille donc fortement de déplacer cette décision au niveau de l'application. Vous pouvez marquer le cache comme étant "local" et d'autres étant "en cluster". Mais vous devriez probablement avoir une sorte de nomenclature pour le nom pour le rendre plus facile. Ne choisissez pas un gestionnaire de cache au niveau du module.

ce billet de blog illustre cela avec d'autres exemples.

33
Stephane Nicoll

Comme l'explique @Stephane Nicoll, vous avez plusieurs options. Je vais essayer de donner quelques informations sur les CacheResolver personnalisés. CacheResolver a une méthode:

Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);

qui donne un contexte à la classe, la méthode, les arguments, etc. de l'opération pouvant être mise en cache.

Dans sa forme de base:

public class CustomCacheResolver implements CacheResolver {

    private final CacheManager cacheManager;

    public CustomCacheResolver(CacheManager cacheManager){
        this.cacheManager = cacheManager;
    }

    @Override
    public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
        Collection<Cache> caches = getCaches(cacheManager, context);
        return caches;
    }

    private Collection<Cache> getCaches(CacheManager cacheManager, CacheOperationInvocationContext<?> context) {
        return context.getOperation().getCacheNames().stream()
            .map(cacheName -> cacheManager.getCache(cacheName))
            .filter(cache -> cache != null)
            .collect(Collectors.toList());
    }
}

Ici, j'utilise un CacheManager par souci de concision. Mais vous pouvez lier différents CacheManager à CacheResolver et effectuer des sélections plus granulaires: si le nom de la classe est X, alors utilisez GuavaCacheManager, sinon utilisez EhCacheCacheManager.

Après cette étape, vous devez enregistrer CacheResolver, (encore une fois, vous pouvez lier plus CacheManagers ici):

@Configuration
@EnableCaching
public class CacheConfiguration extends CachingConfigurerSupport {

    @Bean
    @Override
    public CacheManager cacheManager() {
        // Desired CacheManager
    }

    @Bean
    @Override
    public CacheResolver cacheResolver() {
        return new CustomCacheResolver(cacheManager());
    }
}

Et comme dernière étape, vous devez spécifier CustomCacheResolver dans l'un des @Cacheable, @CachePut, @CacheConfig etc. annotations.

@Cacheable(cacheResolver="cacheResolver")

Vous pouvez regarder ici pour des exemples de code.

5
isaolmez