Creating custom cache key from target object properties using SpEL

In this post under Spring Caching, I will show with example how to create custom cache key using annotated method’s target object properties in SpEL.

For our example, we will use the below “Calculator” class as shown below

Calculator

package caching.package8;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class Calculator {
private int start, end;
@Cacheable(cacheNames = "addNumbersWithParam_region", key = "#root.target.start * #root.target.end")
public int addNumbersWithParam() {
System.out.println("Calculating addNumbersWithParam");
int result = 1;
for(int i = start; i <= end; i++) {
result = result + i;
}
return result;
}
//Removed getter and setter for brevity
}

In the above class, I have defined two integer properties “start” and “end”, using which I will create the custom cache key.

In the above code, at line 10, I used “@Cacheable” annotation with cache region name “addNumbersWithParam_region” and “key” equal to “#root.target.start * #root.target.end”.

The method which is annotated with “@Cacheable” is named as “addNumbersWithParam”.

In the SpEL code, I have accessed the annotated method’s target object property “start” using “#root.target.start” and “end” using “#root.target.end” to generate custom cache key.

In the expression “target” refers to the object in which the method is defined.

So when we call the method with target object property “start” equal to “5” and “end” equal to “100” and the key will be “500”.

In this way, we can create custom cache key using annotated method’s target object properties in SpEL.

Below is the complete main class for your example.

Main class

package caching.package8;
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.package8")
public class Example8 {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Example8.class);
Calculator calculator = annotationConfigApplicationContext.getBean(Calculator.class);
calculator.setStart(1);
calculator.setEnd(100);
System.out.println("First time addNumbersWithParam call started");
System.out.println(calculator.addNumbersWithParam());
System.out.println("First time addNumbersWithParam call finished");
System.out.println("-------------------------------------");
System.out.println("Second time addNumbersWithParam call started");
System.out.println(calculator.addNumbersWithParam());
System.out.println("Second time addNumbersWithParam call finished");
System.out.println("-------------------------------------");
}
}

Below is the output

Output

First time addNumbersWithParam call started
Calculating addNumbersWithParam
5051
First time addNumbersWithParam call finished
-------------------------------------
Second time addNumbersWithParam call started
5051
Second time addNumbersWithParam call finished
-------------------------------------

Leave a comment