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
- reference to target method that is annotated with @Cacheable, @CachePut, or @CacheEvict
- reference to target object containing the annotated method
- reference to Class object of the target object
- annotated target method name
- annotated target method arguments
- 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;@Componentpublic 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 startedCalculating addNumbersWithParam5051First time addNumbersWithParam(1, 100) call finished-------------------------------------Second time addNumbersWithParam(1, 100) call started5051Second time addNumbersWithParam(1, 100) call finished-------------------------------------
In this way, we can create a custom key using method arguments in SpEL