Spring Bootにおけるキャッシュの有効化と利用方法

依存関係の追加

Spring側にはキャッシュ処理のインターフェースのみ用意されているので、キャッシュ使用時には別途実装を用意する必要がある。
Caffeineはキャッシュの実装を提供するモジュールである。

dependencies {
  // Spring Boot Starter Cache
  implementation 'org.springframework.boot:spring-boot-starter-cache'
  // Caffeine
  implementation "com.github.ben-manes.caffeine:caffeine:3.0.5"
}

キャッシュを有効化する

アプリでキャッシュ機能を有効化するためにMainクラスに「@EnableCachingアノテーションを付与する。

Mainクラスのほかに、「@Configurationアノテーションが付与されているJavaConfigクラスに付与しても良い。
アプリが特定の機能を使用する際のみキャッシュを有効化したい場合などに使用する。

import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class WebappApplication {

    /**
     * Webアプリケーションを起動する。<br>
     *
     * @param args
     *            起動時引数
     */
    public static void main(String[] args) {
        SpringApplication.run(WebappApplication.class, args);
    }
}

キャッシュを使用するメソッドの定義

メソッド実行結果をキャッシュしたいメソッドに「@Cacheableアノテーションを付与する。
また、キャッシュしたいメソッドを含むクラスは、プロジェクトで使用する際にはDIコンテナに登録する。
(※SpringBootでのキャッシュはAOPの機能を利用して実装されているため)

import org.springframework.cache.annotation.Cacheable;

@Component
public class CacheSample {
    @Cacheable(cacheNames = "sampleCache", sync = true)
    public int cache(int num) {
        return num * 2;
    }
}

@Cacheableの属性について

cacheNames

メソッドの実行結果を格納するキャッシュの名前。

key

キーを動的に計算するSpEL式。
デフォルトは空文字で、カスタムkeyGeneratorが設定されていない限り、すべてのメソッドパラメータがキーとみなされる。

SpEL式は、以下のメタデータを提供する専用のコンテキストに対して評価される:

  • #root.method#root.target#root.caches:それぞれメソッド、ターゲットオブジェクト、および影響を受けるキャッシュへの参照
  • #root.methodName#root.targetClass:それぞれメソッド名、ターゲットクラスへの参照
  • メソッドパラーメータへのインデックスアクセス:例えば第2引数へは#root.args[1]#p1#a1で参照可能

keyGenerator

独自のキージェネレータ(org.springframework.cache.interceptor.KeyGenerator)のbean名。

cacheManager

デフォルトのキャッシュリゾルバ(org.springframework.cache.interceptor.CacheResolver)が設定されていない場合に、キャッシュリゾルバを作成するために使用するキャッシュマネージャー(org.springframework.cache.CacheManager)のbean名。

cacheResolver

独自のキャッシュリゾルバ(org.springframework.cache.interceptor.CacheResolver)のbean名。

condition

メソッドキャッシュの条件を定義したSpEL式。
デフォルトは空文字で、メソッドの結果が常にキャッシュされることを意味する。

SpEL式は、以下のメタデータを提供する専用のコンテキストに対して評価される:

  • #root.method#root.target#root.caches:それぞれメソッド、ターゲットオブジェクト、および影響を受けるキャッシュへの参照
  • #root.methodName#root.targetClass:それぞれメソッド名、ターゲットクラスへの参照
  • メソッドパラーメータへのインデックスアクセス:例えば第2引数へは#root.args[1]#p1#a1で参照可能

unless

メソッドのキャッシュを拒否する条件を定義したSpEL式。
デフォルトは空文字で、キャッシュが拒否される条件は特にないことを意味する。

condition属性とは異なり、この式はメソッドが呼び出された後に評価されるので、 メソッド実行結果を参照することができる。

SpEL式は、以下のメタデータを提供する専用のコンテキストに対して評価される:

  • #result:メソッド呼び出しの結果への参照。Optionalなどのラッパーでは、#resultはラッパーではなく実際のオブジェクトを参照する。
  • #root.method#root.target#root.caches:それぞれメソッド、ターゲットオブジェクト、および影響を受けるキャッシュへの参照
  • #root.methodName#root.targetClass:それぞれメソッド名、ターゲットクラスへの参照
  • メソッドパラーメータへのインデックスアクセス:例えば第2引数へは#root.args[1]#p1#a1で参照可能

sync

複数のスレッドが同じキーの値をロードしようとしている場合、メソッドの呼び出しを同期させるかどうか。
同期には以下の制限がある:

  • unless属性は使用不可
  • 指定できるキャッシュは1つのみ
  • 他のキャッシュ関連操作を組み合わせることはできない

キャッシュの設定

キャッシュを使用するプロジェクトのapplication.ymlで、キャッシュの有効期限などの設定を行う。

# Spring Cacheの設定
spring:
  cache:
    # キャッシュの名前(コンマ区切りで複数選択可能)
    cache-names: sampleCache
    # キャッシュの有効期限(キャッシュ作成から削除までの時間)
    caffeine:
      spec: expireAfterWrite=30m

キャッシュを使用するメソッドの呼び出し

キャッシュを使用するメソッドも他のメソッドと同じように呼び出せばよい。

@Service
public class SampleServiceImpl implements SampleService {

    private CacheSample cacheSample;

    public SampleServiceImpl(CacheSample cacheSample) {
        this.cacheSample = cacheSample;
    }

    @Override
    public void execute(int num) {
        int result = cacheSample.cache(num);
    }
}