In this post under Spring Caching, I will show with example how to enable conditional caching using SpEL.
In previous posts I showed you how to use “@Cacheable” annotation.
In that annotation itself there is an attribute that we can use to enable conditional caching.
That attribute name is “condition” and it takes as SpEL expression as value.
If the result of that SpEL expression is true, the method result is cached if not the method result is not cached.
For our example, I will use the below class
Calculator
package caching.package9;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]", condition = "(#root.args[1] - #root.args[0]) > 100") 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; }}
As you can see in the above code, I have used “condition” attribute in “@Cacheable” annotation.
The value of the attribute is an SpEL expression “(#root.args[1] – #root.args[0]) > 100”.
The expression substracts first and second parameters and checks if the difference is greater than 100 or not. if greater returns true or else false.
So if I call the method “addNumbersWithParam” with parameters 1 and 100. Where “start” is 1 and “end” is 100, the difference 99 is not greater than 100 and the result of the method is not saved in the cache.
If I call the method “addNumbersWithParam” with parameters 1 and 1000. Where “start” is 1 and “end” is 1000, the difference 999 is greater than 100 and the result of the methd is saved in the cache.
Below is the complete main method for your reference.
Main class
package caching.package9;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.package9")public class Example9 { @Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager(); } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Example9.class); Calculator calculator = context.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("-------------------------------------"); System.out.println("First time addNumbersWithParam(1, 1000) call started"); System.out.println(calculator.addNumbersWithParam(1, 1000)); System.out.println("First time addNumbersWithParam(1, 1000) call finished"); System.out.println("-------------------------------------"); System.out.println("Second time addNumbersWithParam(1, 1000) call started"); System.out.println(calculator.addNumbersWithParam(1, 1000)); System.out.println("Second time addNumbersWithParam(1, 1000) 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 startedCalculating addNumbersWithParam5051Second time addNumbersWithParam(1, 100) call finished-------------------------------------First time addNumbersWithParam(1, 1000) call startedCalculating addNumbersWithParam500501First time addNumbersWithParam(1, 1000) call finished-------------------------------------Second time addNumbersWithParam(1, 1000) call started500501Second time addNumbersWithParam(1, 1000) call finished-------------------------------------
As you can see from the output, when we called “addNumbersWithParam” with parameters 1 and 100 first and second time. The method was executed. Cache was not used at all.
But when we called the same method “addNumbersWithParam” with parameters 1 and 1000 first and second time. First time call the method was executed but during the second time call, the method was not executed and the value was taken from cache.
In this way we can enable conditional caching.