Creating custom cache key from method arguments using SpEL

In this post under Spring Caching, I will show with example how to create custom cache key from method arguments in SpEL.

In SpEL, to access SpEL context object we will use “#root” variable.

This SpEL context object will have below information

  1. reference to target method that is annotated with @Cacheable, @CachePut, or @CacheEvict
  2. reference to target object containing the annotated method
  3. reference to Class object of the target object
  4. annotated target method name
  5. annotated target method arguments
  6. collection of caches used by target method

We can use these information to create our own custom key in SpEL.

Here in this post, I will show how to access method arguments in SpEL to create our own custom cache key.

For our example, I will use the below “Calculator” class

Calculator

package caching.package5;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class Calculator {
@Cacheable(cacheNames = "addNumbersWithParam_region", key = "#root.args[0] * #root.args[1]")
public int addNumbersWithParam(int start, int end) {
System.out.println("Calculating addNumbersWithParam");
int result = 1;
for(int i = start; i <= end; i++) {
result = result + i;
}
return result;
}
}

In the above code, at line 8, I have used “@Cacheable” annotation for the method “addNumbersWithParam”.

The cache region name I have given is “addNumbersWithParam_region”.

The SpEL that I have used to generate custom cache key is “#root.args[0] * #root.args[1]” and assigned it to “key” attribute of “@Cacheable” annotation.

I have used the “args” array of “#root” object to access the method arguments.

The methods first argument start with index 0.

So in our example “#root.args[0]” refers to method argument “start” and “#root.args[1]” refers to method argument “end”.

At runtime if I call the method with arguments “start = 5” and “end = 100”, the key will be “500”, and the value will be sum of all numbers from 5 to 100.

Next time when I call the method with same arguments, the value is retrieved from the cache using the key “500” instead of executing the method again.

Below is the main class for your reference.

Main class

package caching.package5;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@EnableCaching
@Configuration
@ComponentScan(basePackages = "caching.package5")
public class Example5 {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Example5.class);
Calculator calculator = annotationConfigApplicationContext.getBean(Calculator.class);
System.out.println("First time addNumbersWithParam(1, 100) call started");
System.out.println(calculator.addNumbersWithParam(1, 100));
System.out.println("First time addNumbersWithParam(1, 100) call finished");
System.out.println("-------------------------------------");
System.out.println("Second time addNumbersWithParam(1, 100) call started");
System.out.println(calculator.addNumbersWithParam(1, 100));
System.out.println("Second time addNumbersWithParam(1, 100) call finished");
System.out.println("-------------------------------------");
}
}

Below is the output

Output

First time addNumbersWithParam(1, 100) call started
Calculating addNumbersWithParam
5051
First time addNumbersWithParam(1, 100) call finished
-------------------------------------
Second time addNumbersWithParam(1, 100) call started
5051
Second time addNumbersWithParam(1, 100) call finished
-------------------------------------

In this way, we can create a custom key using method arguments in SpEL

Leave a comment