124 lines
5.2 KiB
Plaintext
124 lines
5.2 KiB
Plaintext
[[cache-jsr-107]]
|
|
= JCache (JSR-107) Annotations
|
|
|
|
Since version 4.1, Spring's caching abstraction fully supports the JCache standard
|
|
(JSR-107) annotations: `@CacheResult`, `@CachePut`, `@CacheRemove`, and `@CacheRemoveAll`
|
|
as well as the `@CacheDefaults`, `@CacheKey`, and `@CacheValue` companions.
|
|
You can use these annotations even without migrating your cache store to JSR-107.
|
|
The internal implementation uses Spring's caching abstraction and provides default
|
|
`CacheResolver` and `KeyGenerator` implementations that are compliant with the
|
|
specification. In other words, if you are already using Spring's caching abstraction,
|
|
you can switch to these standard annotations without changing your cache storage
|
|
(or configuration, for that matter).
|
|
|
|
|
|
[[cache-jsr-107-summary]]
|
|
== Feature Summary
|
|
|
|
For those who are familiar with Spring's caching annotations, the following table
|
|
describes the main differences between the Spring annotations and their JSR-107
|
|
counterparts:
|
|
|
|
.Spring vs. JSR-107 caching annotations
|
|
[cols="1,1,3"]
|
|
|===
|
|
| Spring | JSR-107 | Remark
|
|
|
|
| `@Cacheable`
|
|
| `@CacheResult`
|
|
| Fairly similar. `@CacheResult` can cache specific exceptions and force the
|
|
execution of the method regardless of the content of the cache.
|
|
|
|
| `@CachePut`
|
|
| `@CachePut`
|
|
| While Spring updates the cache with the result of the method invocation, JCache
|
|
requires that it be passed it as an argument that is annotated with `@CacheValue`.
|
|
Due to this difference, JCache allows updating the cache before or after the
|
|
actual method invocation.
|
|
|
|
| `@CacheEvict`
|
|
| `@CacheRemove`
|
|
| Fairly similar. `@CacheRemove` supports conditional eviction when the
|
|
method invocation results in an exception.
|
|
|
|
| `@CacheEvict(allEntries=true)`
|
|
| `@CacheRemoveAll`
|
|
| See `@CacheRemove`.
|
|
|
|
| `@CacheConfig`
|
|
| `@CacheDefaults`
|
|
| Lets you configure the same concepts, in a similar fashion.
|
|
|===
|
|
|
|
JCache has the notion of `javax.cache.annotation.CacheResolver`, which is identical
|
|
to the Spring's `CacheResolver` interface, except that JCache supports only a single
|
|
cache. By default, a simple implementation retrieves the cache to use based on the
|
|
name declared on the annotation. It should be noted that, if no cache name is
|
|
specified on the annotation, a default is automatically generated. See the javadoc
|
|
of `@CacheResult#cacheName()` for more information.
|
|
|
|
`CacheResolver` instances are retrieved by a `CacheResolverFactory`. It is possible
|
|
to customize the factory for each cache operation, as the following example shows:
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes"]
|
|
----
|
|
@CacheResult(cacheNames="books", cacheResolverFactory=MyCacheResolverFactory.class) <1>
|
|
public Book findBook(ISBN isbn)
|
|
----
|
|
<1> Customizing the factory for this operation.
|
|
|
|
NOTE: For all referenced classes, Spring tries to locate a bean with the given type.
|
|
If more than one match exists, a new instance is created and can use the regular
|
|
bean lifecycle callbacks, such as dependency injection.
|
|
|
|
Keys are generated by a `javax.cache.annotation.CacheKeyGenerator` that serves the
|
|
same purpose as Spring's `KeyGenerator`. By default, all method arguments are taken
|
|
into account, unless at least one parameter is annotated with `@CacheKey`. This is
|
|
similar to Spring's xref:integration/cache/annotations.adoc#cache-annotations-cacheable-key[custom key generation declaration]
|
|
. For instance, the following are identical operations, one using
|
|
Spring's abstraction and the other using JCache:
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes"]
|
|
----
|
|
@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)
|
|
----
|
|
|
|
You can also specify the `CacheKeyResolver` on the operation, similar to how you can
|
|
specify the `CacheResolverFactory`.
|
|
|
|
JCache can manage exceptions thrown by annotated methods. This can prevent an update of
|
|
the cache, but it can also cache the exception as an indicator of the failure instead of
|
|
calling the method again. Assume that `InvalidIsbnNotFoundException` is thrown if the
|
|
structure of the ISBN is invalid. This is a permanent failure (no book could ever be
|
|
retrieved with such a parameter). The following caches the exception so that further
|
|
calls with the same, invalid, ISBN throw the cached exception directly instead of
|
|
invoking the method again:
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes"]
|
|
----
|
|
@CacheResult(cacheName="books", exceptionCacheName="failures"
|
|
cachedExceptions = InvalidIsbnNotFoundException.class)
|
|
public Book findBook(ISBN isbn)
|
|
----
|
|
|
|
|
|
[[enabling-jsr-107-support]]
|
|
== Enabling JSR-107 Support
|
|
|
|
You do not need to do anything specific to enable the JSR-107 support alongside Spring's
|
|
declarative annotation support. Both `@EnableCaching` and the `cache:annotation-driven`
|
|
XML element automatically enable the JCache support if both the JSR-107 API and the
|
|
`spring-context-support` module are present in the classpath.
|
|
|
|
NOTE: Depending on your use case, the choice is basically yours. You can even mix and
|
|
match services by using the JSR-107 API on some and using Spring's own annotations on
|
|
others. However, if these services impact the same caches, you should use a consistent
|
|
and identical key generation implementation.
|
|
|
|
|
|
|