Spring Cache - SGajre/Tutorial GitHub Wiki

Declarative annotation-based caching

  • For caching declaration, the abstraction provides a set of Java annotations:
  1. @Cacheable triggers cache population
  2. @CacheEvict triggers cache eviction
  3. @CachePut updates the cache without interfering with the method execution
  4. @Caching regroups multiple cache operations to be applied on a method
  5. @CacheConfig shares some common cache-related settings at class-level

@Cacheable("books") public Book findBook(ISBN isbn) {...}

@Cacheable({"books", "isbns"}) public Book findBook(ISBN isbn) {...}


KeyGenerator:

  • If no params are given, return SimpleKey.EMPTY.

  • If only one param is given, return that instance.

  • If more the one param is given, return a SimpleKey containing all parameters.

  • To provide a different default key generator, one needs to implement the Org.springframework.cache.interceptor.KeyGenerator interface.

Custom Key Generation Declaration

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

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

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

  • to generate the key is too specific or if it needs to be shared, you may define a custom keyGenerator on the operation

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

Custom cache resolution

  • The default cache resolution fits well for applications working with a single CacheManager and with no complex cache resolution requirements.

  • For applications working with several cache managers, it is possible to set the cacheManager to use per operation: @Cacheable(cacheNames="books", cacheManager="anotherCacheManager") public Book findBook(ISBN isbn) {...}

  • Synchronized caching @Cacheable(cacheNames="foos", sync="true") public Foo executeExpensiveOperation(String id) {...}

  • Conditional caching @Cacheable(cacheNames="book", condition="#name.length() < 32") public Book findBook(String name)

  • Unlike condition, unless expressions are evaluated after the method has been called.

@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback") public Book findBook(String name)

@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result?.hardback")


@CachePut annotation public Optional findBook(String name)

  • Note that using @CachePut and @Cacheable annotations on the same method is generally strongly discouraged because they have different behaviors.
  • While the latter causes the method execution to be skipped by using the cache, the former forces the execution in order to execute a cache update. This leads to unexpected behavior

@CacheEvict annotation

Opposed to @Cacheable, annotation @CacheEvict demarcates methods that perform cache eviction, that is methods that act as triggers for removing data from the cache.

@CacheEvict(cacheNames="books", allEntries=true) public void loadBooks(InputStream batch)

@CacheEvict(cacheNames="books", allEntries=true , beforeInvocation = ture) public void loadBooks(InputStream batch)

beforeInvocation=true causes the eviction to occur always

  • It is important to note that void methods can be used with @CacheEvict - as the methods act as triggers, the return values are ignored (as they don’t interact with the cache) - this is not the case with @Cacheable which adds/updates data into the cache and thus requires a result.

@Caching annotation @Caching allows multiple nested @Cacheable, @CachePut and @CacheEvict to be used on the same method:

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") }) public Book importBooks(String deposit, Date date)


@CacheConfig("books") public class BookRepositoryImpl implements BookRepository { @Cacheable public Book findBook(ISBN isbn) {...} }

  • @CacheConfig is a class-level annotation that allows to share the cache names, the custom KeyGenerator, the custom CacheManager and finally the custom CacheResolver. Placing this annotation on the class does not turn on any caching operation.

three levels of customization per cache operation:

  • Globally configured, available for CacheManager, KeyGenerator
  • At class level, using @CacheConfig
  • At the operation level

@Configuration @EnableCaching public class AppConfig { } @CacheConfig annotation


JCache:

@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 to pass it as an argument that is annotated with @CacheValue. Due to this difference, JCache allows to update the cache before or after the actual method invocation.

@CacheEvict -- @CacheRemove -- Fairly similar. @CacheRemove supports a conditional evict in case the method invocation results in an exception.

@CacheEvict(allEntries=true) -- @CacheRemoveAll -- See @CacheRemove.

@CacheConfig -- @CacheDefaults --Allows to configure the same concepts, in a similar fashion.


⚠️ **GitHub.com Fallback** ⚠️