1. Обзор
В этом руководстве мы узнаем, как настроить несколько менеджеров кеша в приложении Spring.
2. Кэширование
Spring применяет кэширование к методам, чтобы наше приложение не выполняло один и тот же метод несколько раз для одного и того же ввода.
Реализовать кэширование в приложении Spring очень просто . Это можно сделать, добавив аннотацию @EnableCaching
в наш класс конфигурации:
@Configuration
@EnableCaching
public class MultipleCacheManagerConfig {}
Затем мы можем начать кэшировать вывод метода, добавив аннотацию @Cacheable
к методу:
@Cacheable(cacheNames = "customers")
public Customer getCustomerDetail(Integer customerId) {
return customerDetailRepository.getCustomerDetail(customerId);
}
Как только мы добавим указанную выше конфигурацию, Spring Boot сам создаст для нас менеджер кеша.
По умолчанию он использует ConcurrentHashMap
в качестве базового кеша, если мы явно не указали какой-либо другой .
3. Настройка нескольких менеджеров кэша
В некоторых случаях нам может понадобиться использовать более одного менеджера кеша в нашем приложении. Итак, давайте посмотрим, как мы можем сделать это в нашем приложении Spring Boot на примере.
В нашем примере мы будем использовать CaffeineCacheManager
и простой ConcurrentMapCacheManager
.
CaffeineCacheManager
предоставляется стартером spring-boot-starter-cache
. Он будет автоматически настроен Spring, если присутствует Caffeine
, который представляет собой библиотеку кэширования, написанную на Java 8.
ConcurrentMapCacheManager
использует реализацию кеша с использованием C oncurrentHashMap
.
Мы можем сделать это следующими способами.
3.1. Использование @Primary
Мы можем создать два bean-компонента менеджеров кеша в нашем классе конфигурации. Затем мы можем сделать один компонент основным:
@Configuration
@EnableCaching
public class MultipleCacheManagerConfig {
@Bean
@Primary
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("customers", "orders");
cacheManager.setCaffeine(Caffeine.newBuilder()
.initialCapacity(200)
.maximumSize(500)
.weakKeys()
.recordStats());
return cacheManager;
}
@Bean
public CacheManager alternateCacheManager() {
return new ConcurrentMapCacheManager("customerOrders", "orderprice");
}
}
Теперь Spring Boot будет использовать CaffeineCacheManager
по умолчанию для всех методов, пока мы явно не укажем наш alterCacheManager
для метода:
@Cacheable(cacheNames = "customers")
public Customer getCustomerDetail(Integer customerId) {
return customerDetailRepository.getCustomerDetail(customerId);
}
@Cacheable(cacheNames = "customerOrders", cacheManager = "alternateCacheManager")
public List<Order> getCustomerOrders(Integer customerId) {
return customerDetailRepository.getCustomerOrders(customerId);
}
В приведенном выше примере наше приложение будет использовать CaffeineCacheManager
для метода getCustomerDetail()
. А для метода getCustomerOrders()
он будет использовать alterCacheManager .
3.2. Расширение CachingConfigurerSupport
Другой способ сделать это — расширить класс CachingConfigurerSupport
и переопределить метод cacheManager
(). Этот метод возвращает bean-компонент, который будет менеджером кеша по умолчанию для нашего приложения:
@Configuration
@EnableCaching
public class MultipleCacheManagerConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("customers", "orders");
cacheManager.setCaffeine(Caffeine.newBuilder()
.initialCapacity(200)
.maximumSize(500)
.weakKeys()
.recordStats());
return cacheManager;
}
@Bean
public CacheManager alternateCacheManager() {
return new ConcurrentMapCacheManager("customerOrders", "orderprice");
}
}
Обратите внимание, что мы все еще можем создать еще один компонент с именем alterCacheManager.
Мы можем использовать этот alterCacheManager
для метода, явно указав его, как в последнем примере.
3.3. Использование CacheResolver
Мы можем реализовать интерфейс CacheResolver
и создать собственный CacheResolver
:
public class MultipleCacheResolver implements CacheResolver {
private final CacheManager simpleCacheManager;
private final CacheManager caffeineCacheManager;
private static final String ORDER_CACHE = "orders";
private static final String ORDER_PRICE_CACHE = "orderprice";
public MultipleCacheResolver(CacheManager simpleCacheManager,CacheManager caffeineCacheManager) {
this.simpleCacheManager = simpleCacheManager;
this.caffeineCacheManager=caffeineCacheManager;
}
@Override
public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
Collection<Cache> caches = new ArrayList<Cache>();
if ("getOrderDetail".equals(context.getMethod().getName())) {
caches.add(caffeineCacheManager.getCache(ORDER_CACHE));
} else {
caches.add(simpleCacheManager.getCache(ORDER_PRICE_CACHE));
}
return caches;
}
}
В этом случае нам нужно переопределить метод resolveCaches
интерфейса CacheResolver .
В нашем примере мы выбираем диспетчер кеша на основе имени метода. После этого нам нужно создать bean-компонент нашего пользовательского CacheResolver
:
@Configuration
@EnableCaching
public class MultipleCacheManagerConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("customers", "orders");
cacheManager.setCaffeine(Caffeine.newBuilder()
.initialCapacity(200)
.maximumSize(500)
.weakKeys()
.recordStats());
return cacheManager;
}
@Bean
public CacheManager alternateCacheManager() {
return new ConcurrentMapCacheManager("customerOrders", "orderprice");
}
@Bean
public CacheResolver cacheResolver() {
return new MultipleCacheResolver(alternateCacheManager(), cacheManager());
}
}
Теперь мы можем использовать наш пользовательский CacheResolver
для разрешения диспетчера кеша для наших методов:
@Component
public class OrderDetailBO {
@Autowired
private OrderDetailRepository orderDetailRepository;
@Cacheable(cacheNames = "orders", cacheResolver = "cacheResolver")
public Order getOrderDetail(Integer orderId) {
return orderDetailRepository.getOrderDetail(orderId);
}
@Cacheable(cacheNames = "orderprice", cacheResolver = "cacheResolver")
public double getOrderPrice(Integer orderId) {
return orderDetailRepository.getOrderPrice(orderId);
}
}
Здесь мы передаем имя нашего bean -компонента CacheResolver в элементе
cacheResolver
.
4. Вывод
В этой статье мы узнали, как включить кэширование в нашем приложении Spring Boot. Затем мы узнали три способа использования нескольких менеджеров кеша в нашем приложении.
Как всегда, код этих примеров доступен на GitHub .