Spring Cache Custom KeyGenerator

In this post, we will explore how to create a custom key generator with Spring Cache. Read our article cache Spring Caching the Spring cache introduction.



Since caches are essentially key-value stores, each invocation of a cached method needs translation into a suitable key for cache access. In this post, we are covering the default key generation features provided by Spring Cache API. We are also going to cover the option to create a custom key generator with Spring Cache.


1. KeyGenerator

Spring Cache API uses a simple KeyGenerator for generating a key to store caching data. The default key generators for Spring Cache SimpleKeyGenerator.This default implementation uses the method parameters to generate the key. Here is the high-level overview for the default key generation algorithm.

  • If no params are given, return SimpleKey.EMPTY.
  • With only one parameter, return that instance.
  • If more the one param is given, return a SimpleKey containing all parameters.

Above approach works for most of the use cases, however, there are certain use cases where the above algorithm can cause collision while creating the key.

  •  In the case of two methods with the same parameters and cache name.

Let’s look at an example to understand this more clearly.

@CacheConfig(cacheNames = "customer")
public class CustomerService {

 public Customer getCustomer(Integer customerId) {
  return // ...

 public EliteCustomer getEliteCustomer(Integer id) {
  return // ...


The default key generation strategy changed with the release of Spring 4.0. Earlier versions of Spring used a key generation strategy that, for multiple key parameters, only considered the hashCode() of parameters and not equals();

This could cause unexpected key collisions. The new ‘SimpleKeyGenerator’ uses a compound key for such scenarios.


2. Custom KeyGenerator

Spring Caching API provides options to create a custom key generator for handling all such use cases. To give a different default key generator, we need to implement the org.springframework.cache.interceptor.KeyGenerator interface.KeyGenerator needs to implement a single method.

 * Generate a key for the given method and its parameters.
 * @param target the target instance
 * @param method the method being called
 * @param params the method parameters (with any var-args expanded)
 * @return a generated key
Object generate(Object target, Method method, Object...params);

Let’s take a look at the custom key generator for Spring Caching

public class CustomKeyGenerator implements KeyGenerator {

 public Object generate(Object target, Method method, Object...params) {
  return target.getClass().getSimpleName() + "_" + method.getName() + "_" +
   StringUtils.arrayToDelimitedString(params, "_");

For more complex use cases, we can create a CustomKey class and implement both equals() and hashCode().

public class CustomCacheKey implements Serializable {

 public static final CustomCacheKey EMPTY = new CustomCacheKey();

 private final Object[] params;
 private final int hashCode;

 public CustomCacheKey(Object...elements) {
  Assert.notNull(elements, "null value");
  this.params = new Object[elements.length];
  System.arraycopy(elements, 0, this.params, 0, elements.length);
  this.hashCode = Arrays.deepHashCode(this.params);

 public boolean equals(Object obj) {
  return (this == obj || (obj instanceof CustomCacheKey &&
   Arrays.deepEquals(this.params, ((CustomCacheKey) obj).params)));

 public final int hashCode() {
  return this.hashCode;

 public String toString() {
  return getClass().getSimpleName() + " [" + StringUtils.arrayToCommaDelimitedString(this.params) + "]";

This is how our custom key generator looks like

public class CustomKeyGenerator implements KeyGenerator {

 public Object generate(Object target, Method method, Object...params) {
  return generateKey(params);

  * Generate a key based on the specified parameters.
 public static Object generateKey(Object...params) {
  if (params.length == 0) {
   return CustomCacheKey.EMPTY;
  if (params.length == 1) {
   Object param = params[0];
   if (param != null && !param.getClass().isArray()) {
    return param;
  return new CustomCacheKey(params);


3. Using Custom KeyGenerator

We have our custom key generator, to use it, we have the following two options to use the custom key in our Spring Cache application.


3.1 Use CachingConfigurerSupport

The first option is to implement CachingConfigurer. Recommendation is to extend from CachingConfigurerSupport.

public class ApplicationConfig extends CachingConfigurerSupport {

 public KeyGenerator keyGenerator() {
  return new CustomKeyGenerator();

Extending from CachingConfigurerSupport helps in registering the declared KeyGenerator with the interceptors.


3.2 Method Level KeyGenerator

If you like to use, a custom key generator for certain methods, pass it as keyGenerator attribute in the @Cacheable annotation.

public class DefaultProductService implements ProductService {

 @Cacheable("products", keyGenerator = "customKeyGenerator")
 public List < Product > getProducts() {

  List < Product > productList = new ArrayList < > ();
  for (int i = 0; i < 9; i++) {
   productList.add(new Product(String.valueOf(i), "Demo Product", "Sample Description"));
  return productList;


3.3 SPEL Expressions

The @Cacheable annotation allows the user to specify key generation algorithm through its key attribute. We can use  SpEL to pick the arguments for key generation. Here are some of the examples.

@Cacheable(cacheNames="address", key="#customer")
public Address getAddress(final Customer customer)() {...}

@Cacheable(cacheNames="address", key="#customer.id")
public Address getAddress(final Customer customer)() {...}

The key and keyGenerator parameters are mutually exclusive and an operation specifying both will result in an exception.



In this article, we explore how to create a custom key generator with Spring Cache. We discuss the features and capabilities of the default key generator. We also discuss the steps of implementing a custom Spring Cache’s KeyGenerator.

You can download the source code for this post from GitHub

0 0 vote
Article Rating

Java Development Journal

Hello!! Welcome to the Java Development Journal. We love to share our knowledge with our readers and love to build a thriving community.

follow me on:
Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Inline Feedbacks
View all comments
Would love your thoughts, please comment.x