1. 概要

このチュートリアルでは、Springアプリケーションで複数のキャッシュマネージャーを構成する方法を学習します。

2. キャッシング

Springはメソッドにキャッシュを適用して、アプリケーションが同じ入力に対して同じメソッドを複数回実行しないようにします。

実装は非常に簡単です Springアプリケーションでのキャッシングこれは、を追加することによって行うことができます @EnableCaching 構成クラスのアノテーション:

@Configuration
@EnableCaching
public class MultipleCacheManagerConfig {}

次に、メソッドに @Cacheable アノテーションを追加することで、メソッドの出力のキャッシュを開始できます。

@Cacheable(cacheNames = "customers")
public Customer getCustomerDetail(Integer customerId) {
    return customerDetailRepository.getCustomerDetail(customerId);
}

上記の構成を追加するとすぐに、SpringBoot自体がキャッシュマネージャーを作成します。

デフォルトでは、他に明示的に指定していない場合、基になるキャッシュとしてConcurrentHashMapを使用します

3. 複数のキャッシュマネージャーの構成

場合によっては、アプリケーションで複数のキャッシュマネージャーを使用する必要があります。 それでは、例を使用して、Spring Bootアプリケーションでこれを行う方法を見てみましょう。

この例では、CaffeineCacheManagerと単純なConcurrentMapCacheManagerを使用します。

CafeineCacheManager は、spring-boot-starter-cacheスターターによって提供されます。 Caffeine が存在する場合、Springによって自動構成されます。これはJava8で記述されたキャッシュライブラリです。

ConcurrentMapCacheManager は、C oncurrentHashMapを使用したキャッシュの実装を使用します。

これは次の方法で実行できます。

3.1. @Primaryを使用する

構成クラスにキャッシュマネージャーの2つのBeanを作成できます。 次に、1つの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は、メソッドに alternateCacheManager を明示的に指定するまで、すべてのメソッドのデフォルトとしてCafeineCacheManagerを使用します。

@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);
}

上記の例では、アプリケーションは getCustomerDetail()メソッドにCafeineCacheManagerを使用します。 そして、 getCustomerOrders() メソッド、それは使用します AlternativeCacheManager。 

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");
    }
}

と呼ばれる別のBeanを作成できることに注意してください AlternativeCacheManager。 これが使えます AlternativeCacheManager 最後の例のように、メソッドを明示的に指定します。

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;
    }
}

この場合、CacheResolverインターフェースのresolveCachesメソッドをオーバーライドする必要があります。

この例では、メソッド名に基づいてキャッシュマネージャーを選択しています。 この後、カスタムCacheResolverの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");
    }

    @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);
    }
}

ここでは、CacheResolverBeanの名前をcacheResolver要素に渡します。

4. 結論

この記事では、SpringBootアプリケーションでキャッシュを有効にする方法を学びました。 次に、アプリケーションで複数のキャッシュマネージャーを使用する3つの方法を学びました。

いつものように、これらの例のコードはGitHubから入手できます。