Я хочу, чтобы в моем веб-приложении было настроено несколько менеджеров кэшей spring, и я мог бы использовать другой менеджер кэша в разных местах моего проекта. Есть ли способ сделать это.
Как настроить конфигурацию менеджера кэшей в spring кеш-java
Ответ 1
Есть несколько способов сделать это, и правильный ответ зависит от того, как вы используете кеш.
У вас есть "главный" менеджер кэша
Если вы используете CacheManager A для 90% вашего варианта использования и B для 10%, я бы посоветовал создать по умолчанию CacheManager
для A (вам нужно будет указать его с помощью расширения CacheConfigurerSupport
), что-то вроде:
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Override
@Bean // not strictly necessary
public CacheManager cacheManager() { ... CacheManager A }
@Bean
public CacheManager bCacheManager() { ... CacheManager B }
}
Затем для 10% сценария использования вы добавляете CacheConfig
вверху классов, которые должны использовать другой менеджер кэша
@CacheConfig(cacheManager="bCacheManager")
public class MyService { /*...*/ }
Если вам нужно использовать другой диспетчер кэша только для одного метода, вы можете указать это и на уровне метода
@Cacheable(cacheNames = "books", cacheManager = "bCacheManager")
public Book findById(long id) { /*...*/ }
Более мелкозернистое разрешение
Если вы не в такой ситуации, вам нужен способ узнать, какой менеджер кэша нужно использовать в каждом конкретном случае. Вы можете сделать это на основе типа цели (MyService
) или имени кэша (books
). Вам нужно будет реализовать CacheResolver
, который сделает этот перевод за вас.
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Override
public CacheResolver cacheResolver() { ... }
}
Проверьте Javadoc CacheResolver
для более подробной информации. В этой реализации у вас может быть несколько экземпляров CacheManager
(в виде бина или нет), которые вы будете вызывать внутри системы на основе вашей логики, чтобы определить, какой менеджер следует использовать.
Я видел в комментарии, что вы имели в виду "модуль". Кэширование - это вопрос инфраструктуры, поэтому я настоятельно рекомендую вам перенести это решение на уровень приложений. Вы можете пометить кеш как локальный, а другие как кластерный. Но вам, вероятно, нужно иметь какую-то номенклатуру для названия, чтобы было легче. Не выбирайте менеджер кеша на уровне модуля.
этот пост иллюстрирует это другими примерами.
Ответ 2
Как объяснил @Stephane Nicoll, у вас есть несколько вариантов.
Я постараюсь дать некоторую информацию о кастомах CacheResolver
. CacheResolver
имеет один метод:
Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);
который предоставляет контекст кешируемому классу операций, методу, аргументам и т.д.
В своей основной форме:
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());
}
}
Здесь я использую один CacheManager
для краткости. Но вы можете привязать разные CacheManager
к CacheResolver
и сделать более детальный выбор: если имя класса - X
, тогда используйте GuavaCacheManager
, в противном случае используйте EhCacheCacheManager
.
После этого шага вы должны зарегистрировать CacheResolver
, (снова вы можете связать больше CacheManagers
здесь):
@Configuration
@EnableCaching
public class CacheConfiguration extends CachingConfigurerSupport {
@Bean
@Override
public CacheManager cacheManager() {
// Desired CacheManager
}
@Bean
@Override
public CacheResolver cacheResolver() {
return new CustomCacheResolver(cacheManager());
}
}
И в качестве последнего шага вы должны указать CustomCacheResolver
в одной из аннотаций @Cacheable
, @CachePut
, @CacheConfig
и т.д.
@Cacheable(cacheResolver="cacheResolver")
Вы можете посмотреть здесь примеры кода.