You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
5.2 KiB
123 lines
5.2 KiB
[[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. |
|
|
|
|
|
|
|
|