Spring Boot Caching
Spring Framework provides caching in a Spring Application, transparently. In Spring, the cache abstraction is a mechanism that allows consistent use of various caching methods with minimal impact on the code.
The cache abstraction mechanism applies to Java methods. The main objective of using cache abstraction is to reduce the number of executions based on the information present in the cache. It applies to expensive methods such as CPU or IO bound.
Every time, when a method invokes, the abstraction applies a cache behavior to the method. It checks whether the method has already been executed for the given argument or not.
Note: This approach works only for the methods that are guaranteed to return the same result for a given input. It does not matter how many times the method executes.
The developers take care of two things while working with cache abstractions.
Caching is a part of temporary memory (RAM). It lies between the application and persistence database. It stores the recently used data that reduces the number of database hits as much as possible. In other words, caching is to store data for future reference.
Why should we use the cache?
The primary reason for using cache is to make data access faster and less expensive. When the highly requested resource is requested multiple times, it is often beneficial for the developer to cache resources so that it can give responses quickly. Using cache in an application enhances the performance of the application. Data access from memory is always faster in comparison to fetching data from the database. It reduces both monetary cost and opportunity cost.
What data should be cached?
Types of Caching
There are four types of caching are as follows:
In-memory caching increases the performance of the application. It is the area that is frequently used. Memcached and Redis are examples of in-memory caching. It stores key-value between application and database. Redis is an in-memory, distributed, and advanced caching tool that allows backup and restore facility. We can manage cache in distributed clusters, also.
Database caching is a mechanism that generates web pages on-demand (dynamically) by fetching the data from the database. It is used in a multi-tier environment that involved clients, web-application server, and database. It improves scalability and performance by distributing a query workload. The most popular database caching is the first level cache of Hibernate.
Web Server Caching
Web server caching is a mechanism that stores data for reuse. For example, a copy of a web page served by a web server. It is cached for the first time when a user visits the page. If the user requests the same next time, the cache serves a copy of the page. It avoids server form getting overloaded. Web server caching enhances the page delivery speed and reduces the work to be done by the backend server.
It is the reason CDN becomes more popular. The CDN reduces the load on an application origin and improves the user experience. It delivers a local copy of the content from a nearby cache edge (a cache server that is closer to the end-user), or a Point of Presence (PoP).
Cache vs. Buffer
Spring Boot Cache Annotations
It is a class-level annotation. We can enable caching in the Spring Boot application by using the annotation @EnableCaching. It is defined in org.springframework.cache.annotation package. It is used together with @Configuration class.
The auto-configuration enables caching and setup a CacheManager, if there is no already defined instance of CacheManager. It scans for a specific provider, and when it does not find, it creates an in-memory cache using concurrent HashMap.
In the following example, @EnableCaching annotation enables the cache mechanism.
It is a class-level annotation that provides a common cache-related setting. It tells the Spring where to store cache for the class. When we annotate a class with the annotation, it provides a set of default settings for any cache operation defined in that class. Using the annotation, we need not to declare things multiple times.
In the following example, employee is the name of the cache.
It is used when we need both annotations @CachePut or @CacheEvict at the same time on the same method. In other words, it is used when we want to use multiple annotations of the same type.
But Java does not allow multiple annotations of the same type to be declared for a given method. To avoid this problem, we use @Caching annotation.
In the following example, we have used the annotation @Caching and grouped all the @CacheEvict annotations.
It is a method level annotation. It defines a cache for a method's return value. The Spring Framework manages the requests and responses of the method to the cache that is specified in the annotation attribute. The @Cacheable annotation contains more options. For example, we can provide a cache name by using the value or cacheNames attribute.
We can also specify the key attribute of the annotation that uniquely identifies each entry in the cache. If we do not specify the key, Spring uses the default mechanism to create the key.
In the following example, we have cached the return value of the method studentInfo() in cacheStudentInfo, and id is the unique key that identifies each entry in the cache.
We can also apply a condition in the annotation by using the condition attribute. When we apply the condition in the annotation, it is called conditional caching.
For example, the following method will be cached if the argument name has a length shorter than 20.
It is a method level annotation. It is used when we want to remove stale or unused data from the cache. It requires one or multiple caches that are affected by the action. We can also specify a key or condition into it. If we want wide cache eviction, the @CacheEvict annotation provides a parameter called allEntries. It evicts all entries rather than one entry based on the key.
One important point about @CacheEvict annotation is that it can be used with void methods because the method acts as a trigger. It avoids return values. On the other hand, the annotation @Cacheable requires a return value that adds/updates data in the cache. We can use @CacheEvict annotation in the following ways:
Evict the whole cache:
Evict an entry by key:
The following annotated method evicts all the data from the cache student_data.
It is a method level annotation. It is used when we want to update the cache without interfering the method execution. It means the method will always execute, and its result will be placed into the cache. It supports the attributes of @Cacheable annotation.
A point to be noticed that the annotations @Cacheable and @CachePut are not the same because they have different behavior. There is a slight difference between @Cacheable and @CachePut annotation is that the @Cacheable annotation skips the method execution while the @CachePut annotation runs the method and put the result into the cache.
The following method will update the cache itself.
Spring Boot Cache Dependency
If we want to enable cache mechanism in a Spring Boot application, we need to add cache dependency in the pom.xml file. It enables caching and configures a CacheManager.
Spring Boot Cache Example
Let's create a Spring Boot application and implement cache mechanism into it.
Step 1: Open Spring Initializr http://start.spring.io.
Step 2: Select the Spring Boot version 2.3.0.M1.
Step 2: Provide the Group name. We have provided com.javatpoint.
Step 3: Provide the Artifact Id. We have provided spring-boot-cache-example.
Step 5: Add the dependencies Spring Web and Spring Cache Abstraction.
Step 6: Click on the Generate button. When we click on the Generate button, it wraps the specifications in a Jar file and downloads it to the local system.
Step 7: Extract the Jar file and paste it into the STS workspace.
Step 8: Import the project folder in STS.
File -> Import -> Existing Maven Projects -> Browse -> Select the folder spring-boot-cache-example -> Finish
It takes some time to import.
Let's open the pom.xml file and see which dependencies we have added into it.
Step 9: Open the SpringBootCacheExampleApplication.java file and enable cache by adding the annotation @EnableCaching.
Step 10: Create a package in the folder src/main/java with the name com.javatpoint.model.
Step 11: In the model package, create a class with the name Customer and define the following:
Step 11: Create a package in the folder src/main/java with the name com.javatpoint.controller.
Step 12: In the Controller package, create a controller class with the name CustomerController and do the following:
Now run the application.
Step 13: Open the SpringBootCacheExampleApplication.java file and run it as Java Application.
Step 14: Open the Postman and send a GET request with the URL http://locahost:8080/custmerinfo. It returns the customer details, as shown below.