JCache(JSR-107)アノテーション

バージョン 4.1 以降、Spring のキャッシング抽象化は、JCache 標準(JSR-107)アノテーション(@CacheResult@CachePut@CacheRemove@CacheRemoveAll および @CacheDefaults@CacheKey@CacheValue コンパニオン)を完全にサポートします。キャッシュストアを JSR-107 に移行しなくても、これらのアノテーションを使用できます。内部実装は Spring のキャッシング抽象化を使用し、仕様に準拠したデフォルトの CacheResolver および KeyGenerator 実装を提供します。つまり、すでに Spring のキャッシュ抽象化を使用している場合は、キャッシュストレージ(または構成)を変更せずに、これらの標準アノテーションに切り替えることができます。

機能の概要

Spring のキャッシングアノテーションに精通している人のために、次の表に Spring アノテーションとそれに対応する JSR-107 の主な違いを示します。

表 1: Spring と JSR-107 キャッシングアノテーション
SpringJSR-107 リマーク

@Cacheable

@CacheResult

かなり似ています。@CacheResult は特定の例外をキャッシュし、キャッシュの内容に関係なくメソッドの実行を強制できます。

@CachePut

@CachePut

Spring はメソッド呼び出しの結果でキャッシュを更新しますが、JCache は @CacheValue アノテーションが付けられた引数としてそれを渡す必要があります。この違いにより、JCache では実際のメソッド呼び出しの前後にキャッシュを更新できます。

@CacheEvict

@CacheRemove

かなり似ています。@CacheRemove は、メソッド呼び出しの結果が例外となった場合の条件付きエビクションをサポートします。

@CacheEvict(allEntries=true)

@CacheRemoveAll

@CacheRemove を参照してください。

@CacheConfig

@CacheDefaults

同様の方法で、同じ概念を構成できます。

JCache の概念は javax.cache.annotation.CacheResolver です。これは、JCache が単一のキャッシュのみをサポートすることを除いて、Spring の CacheResolver インターフェースと同一です。デフォルトでは、単純な実装は、アノテーションで宣言された名前に基づいて使用するキャッシュを取得します。アノテーションにキャッシュ名が指定されていない場合、デフォルトが自動的に生成されることに注意してください。詳細については、@CacheResult#cacheName() の javadoc を参照してください。

CacheResolver インスタンスは CacheResolverFactory によって取得されます。次の例に示すように、キャッシュ操作ごとにファクトリをカスタマイズできます。

@CacheResult(cacheNames="books", cacheResolverFactory=MyCacheResolverFactory.class) (1)
public Book findBook(ISBN isbn)
1 この操作のためにファクトリをカスタマイズします。
すべての参照クラスについて、Spring は指定された型の Bean を見つけようとします。複数の一致が存在する場合、新しいインスタンスが作成され、依存性注入などの通常の Bean ライフサイクルコールバックを使用できます。

キーは、Spring の KeyGenerator と同じ目的を果たす javax.cache.annotation.CacheKeyGenerator によって生成されます。デフォルトでは、少なくとも 1 つのパラメーターに @CacheKey のアノテーションが付けられていない限り、すべてのメソッド引数が考慮されます。これは、Spring のカスタムキー生成宣言に似ています。たとえば、以下は同一の操作で、1 つは Spring の抽象化を使用し、もう 1 つは JCache を使用します。

@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@CacheResult(cacheName="books")
public Book findBook(@CacheKey ISBN isbn, boolean checkWarehouse, boolean includeUsed)

CacheResolverFactory を指定する方法と同様に、操作で CacheKeyResolver を指定することもできます。

JCache は、アノテーション付きメソッドによってスローされた例外を管理できます。これにより、キャッシュの更新を防ぐことができますが、メソッドを再度呼び出す代わりに、失敗のインジケータとして例外をキャッシュすることもできます。ISBN の構造が無効な場合、InvalidIsbnNotFoundException がスローされると仮定します。これは永続的な障害です(このようなパラメーターで本を取得することはできません)。次の例では、例外をキャッシュして、同じ無効な ISBN でさらに呼び出した場合、メソッドを再度呼び出すのではなく、キャッシュされた例外を直接スローします。

@CacheResult(cacheName="books", exceptionCacheName="failures"
			cachedExceptions = InvalidIsbnNotFoundException.class)
public Book findBook(ISBN isbn)

JSR-107 サポートの有効化

Spring の宣言型アノテーションサポートと一緒に JSR-107 サポートを有効にするために、特別なことをする必要はありません。JSR-107 API と spring-context-support モジュールの両方がクラスパスに存在する場合、@EnableCaching と cache:annotation-driven XML 要素の両方が自動的に JCache サポートを有効にします。

ユースケースに応じて、選択は基本的にあなた次第です。一部で JSR-107 API を使用し、他で Spring 独自のアノテーションを使用することで、サービスを組み合わせて使用することもできます。ただし、これらのサービスが同じキャッシュに影響を与える場合は、一貫性のある同一のキー生成実装を使用する必要があります。