Close

Spring Cache - Creating Custom KeyGenerator

[Last Updated: Mar 21, 2018]

In this example we will learn how to implement a custom KeyGenerator

To provide a custom key generator, we need to implement the KeyGenerator interface and register the implementation as a bean.

Examples

package com.logicbig.example;

import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Component("myKeyGen")
public class MyCustomKeyGenerator implements KeyGenerator {
  public Object generate(Object target, Method method, Object... params) {
      StringBuilder sb = new StringBuilder();
      sb.append(target.getClass().getSimpleName())
        .append("-")
        .append(method.getName());

      if (params != null) {
          for (Object param : params) {
              sb.append("-")
                .append(param.getClass().getSimpleName())
                .append(":").append(param);
          }
      }
      return sb.toString();
  }
}

Java Config

@Configuration
@ComponentScan
@EnableCaching
public class AppConfig {
  @Bean
  public CacheManager cacheManager() {
      List<ConcurrentMapCache> caches = Arrays.asList(new ConcurrentMapCache("employee-cache"));
      SimpleCacheManager cacheManager = new SimpleCacheManager();
      cacheManager.setCaches(caches);
      return cacheManager;
  }
}

A service bean

One way to use our custom KeyGenerator is to assign @CacheConfig#keyGenerator element value as our KeyGenerator bean name:

@Service
@CacheConfig(cacheNames = "employee-cache", keyGenerator = "myKeyGen")
public class EmployeeService {

  @Cacheable
  public Employee getEmployeeById(int id) {
      System.out.println("getEmployeeById() invoked");
      return new Employee(id, "Adam", "IT");
  }

  @Cacheable
  public Employee getEmployeeByNameAndDept(String name, String dept) {
      System.out.println("getEmployeeByNameAndDept() invoked");
      return new Employee(20, name, dept);
  }
}

Instead of @Cacheable#keyGenerator, we can also use @CacheConfig.keyGenerator to define/override custom KeyGenerator.

The main class

public class ExampleMain {

  public static void main(String[] args) {
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
      EmployeeService employeeService = context.getBean(EmployeeService.class);
      System.out.println("-- getting employee by id --");
      Employee employee = employeeService.getEmployeeById(10);
      System.out.println("employee returned: " + employee);

      System.out.println("-- getting employee by name and dept --");
      employee = employeeService.getEmployeeByNameAndDept("Linda", "Admin");
      System.out.println("employee returned: " + employee);

      printNativeCache(context);
  }

  public static void printNativeCache(ApplicationContext context) {
      Cache cache = context.getBean(CacheManager.class).getCache("employee-cache");
      System.out.println("-- native cache --");
      Map<String, Object> map = (Map<String, Object>) cache.getNativeCache();
      map.forEach((key, value) -> {
          System.out.println(key + " = " + value);
      });
  }
}
-- getting employee by id --
getEmployeeById() invoked
employee returned: com.logicbig.example.Employee@1d9b7cce
-- getting employee by name and dept --
getEmployeeByNameAndDept() invoked
employee returned: com.logicbig.example.Employee@4d9e68d0
-- native cache --
EmployeeService-getEmployeeById-Integer:10 = com.logicbig.example.Employee@1d9b7cce
EmployeeService-getEmployeeByNameAndDept-String:Linda-String:Admin = com.logicbig.example.Employee@4d9e68d0

Example Project

Dependencies and Technologies Used:

  • spring-context 5.0.4.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.3.9

Spring Custom KeyGenerator Example Select All Download
  • spring-custom-cache-key-generator
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyCustomKeyGenerator.java

    See Also