Spring 3.1 Caching and @cacheable - DZone Java
Spring 3.1 Caching and @cacheable - DZone Java
DZone (/) > Java Zone (/java-jdk-development-tutorials-tools-news) > Spring 3.1 Caching and @Cacheable
Caches have been around in the software world for long time. They’re one of those
really useful things that once you start using them, you wonder how on earth you got
along without them so, it seems a little strange that the Guys at Spring only got around
to adding a caching implementation to Spring core in version 3.1. I’m guessing that
previously it wasn’t seen as a priority and besides, before the introduction of Java
annotations one of the dif iculties of caching was the coupling of caching code with your
business code, which could often become pretty messy.
However, the Guys at Spring have now devised a simple to use caching system based
around a couple of annotations: @Cacheable and @CacheEvict.
The idea of the @Cacheable annotation is that you use it to mark the method return
values that will be stored in the cache.
The @Cacheable annotation can be applied either at method or type level. When
applied at method level, then the annotated method’s return value is cached. When
https://dzone.com/articles/spring-31-caching-and 1/6
10/11/2020 Spring 3.1 Caching and @Cacheable - DZone Java
applied at type level, then the return value of every method is cached.
1 @Cacheable(value = "employee")
2 public class EmployeeDAO {
3
4 public Person findEmployee(String firstName, String surname, int age) {
5
6 return new Person(firstName, surname, age);
7 }
8
9 public Person findAnotherEmployee(String firstName, String surname, int age) {
10
11 return new Person(firstName, surname, age);
12 }
13 }
The Cacheable annotation takes three arguments: value, which is mandatory, together
with key and condition. The irst of these, value, is used to specify the name of the cache
(or caches) in which the a method’s return value is stored.
1 @Cacheable(value = "employee")
2 public Person findEmployee(String firstName, String surname, int age) {
3
4 return new Person(firstName, surname, age);
5 }
The code above ensures that the new Person object is stored in the “employee” cache.
Any data stored in a cache requires a key for its speedy retrieval. Spring, by default,
creates caching keys using the annotated method’s signature as demonstrated by the
code above. You can override this using @Cacheable’s second parameter: key. To de ine
a custom key you use a SpEL expression.
1 @Cacheable(value = "employee", key = "#surname")
2 public Person findEmployeeBySurname(String firstName, String surname, int age) {
3
4 return new Person(firstName, surname, age);
5 }
h l h bl
https://dzone.com/articles/spring-31-caching-and h l d h 2/6
10/11/2020 Spring 3.1 Caching and @Cacheable - DZone Java
The inal @Cacheable argument is the optional condition argument. Again, this
references a SpEL expression, but this time it’s speci ies a condition that’s used to
determine whether or not your method’s return value is added to the cache.
1 @Cacheable(value = "employee", condition = "#age < 25")
2 public Person findEmployeeByAge(String firstName, String surname, int age) {
3
4 return new Person(firstName, surname, age);
5 }
In the code above, I’ve applied the ludicrous business rule of only caching Person
objects if the employee is less than 25 years old.
Having quickly demonstrated how to apply some caching, the next thing to do is to take
a look at what it all means.
1 @Test
2 public void testCache() {
3
4 Person employee1 = instance.findEmployee("John", "Smith", 22);
5 Person employee2 = instance.findEmployee("John", "Smith", 22);
6
7 assertEquals(employee1, employee2);
8 }
The above test demonstrates caching at its simplest. The irst call to indEmployee(...),
the result isn’t yet cached so my code will be called and Spring will store its return value
in the cache. In the second call to indEmployee(...) my code isn’t called and Spring
returns the cached value; hence the local variable employee1 refers to the same object
reference a
1 @Test
2 public void testCacheWithAgeAsCondition() {
3
4 Person employee1 = instance.findEmployeeByAge("John", "Smith", 22);
5 Person employee2 = instance.findEmployeeByAge("John", "Smith", 22);
6
7 assertEquals(employee1, employee2);
8 }
But, things aren’t always so clear cut. Remember that in indEmployeeBySurname I’ve
modi ied the caching key so that the surname argument is used to create the key and the
https://dzone.com/articles/spring-31-caching-and 3/6
10/11/2020 Spring 3.1 Caching and @Cacheable - DZone Java
thing to watch out for when creating your own keying algorithm is to ensure that any
key refers to a unique object.
1 @Test
2 public void testCacheOnSurnameAsKey() {
3
4 Person employee1 = instance.findEmployeeBySurname("John", "Smith", 22);
5 Person employee2 = instance.findEmployeeBySurname("Jack", "Smith", 55);
6
7 assertEquals(employee1, employee2);
8 }
The code above inds two Person instances which are clearly refer to different
employees; however, because I’m caching on surname only, Spring will return a
reference to the object that’s created during my irst call to
indEmployeeBySurname(...). This isn’t a problem with Spring, but with my poor cache
key de inition.
Similar care has to be taken when referring to objects created by methods that have a
condition applied to the @Cachable annotation. In my sample code I’ve applied the
arbitrary condition of only caching Person instances where the employee is under 25
years old.
1 @Test
2 public void testCacheWithAgeAsCondition() {
3
4 Person employee1 = instance.findEmployeeByAge("John", "Smith", 22);
5 Person employee2 = instance.findEmployeeByAge("John", "Smith", 22);
6
7 assertEquals(employee1, employee2);
8 }
In the above code, the references to employee1 and employee2 are equal because in the
second call to indEmployeeByAge(...) Spring returns its cached instance.
1 @Test
2 public void testCacheWithAgeAsCondition2() {
3
4 Person employee1 = instance.findEmployeeByAge("John", "Smith", 30);
5 Person employee2 = instance.findEmployeeByAge("John", "Smith", 30);
6
7 assertFalse(employee1 == employee2);
8 }
Similarly, in the unit test code above, the references to employee1 and employee2 refer
to different objects as, in this case, John Smith is over 25.
https://dzone.com/articles/spring-31-caching-and 4/6
10/11/2020
j , , Spring
J 3.1 Caching and @Cacheable - DZone Java
That just about covers @Cacheable, but what about @CacheEvict and clearing items
form the cache? Also, there’s the question adding caching to your Spring con ig and
choosing a suitable caching implementation. However, more on that later....
Published at DZone with permission of Roger Hughes, DZone MVB. See the original article here.
(http://www.captaindebug.com/2012/09/spring-31-caching-and-cacheable.html)
Opinions expressed by DZone contributors are their own.
Roll your own user auth or integrate pre-built identity management? [Whitepaper]
Okta
Secure a Spring Microservices Architecture with Spring Security and OAuth 2.0
Okta
ABOUT US
About DZone (/pages/about)
Send feedback (mailto:[email protected])
Careers (https://devada.com/careers/)
ADVERTISE
Developer Marketing Blog (https://devada.com/blog/developer-marketing)
Advertise with DZone (/pages/advertise)
+1 (919) 238-7100 (tel:+19192387100)
CONTRIBUTE ON DZONE
https://dzone.com/articles/spring-31-caching-and 5/6
10/11/2020 Spring 3.1 Caching and @Cacheable - DZone Java
LEGAL
Terms of Service (/pages/tos)
Privacy Policy (/pages/privacy)
CONTACT US
600 Park Offices Drive
Suite 150
Research Triangle Park, NC 27709
[email protected] (mailto:[email protected])
+1 (919) 678-0300 (tel:+19196780300)
Let's be friends:
(https://www.linkedin.com/company/devada-
(/pages/feeds)
(https://twitter.com/DZoneInc)
(https://www.facebook.com/DZoneInc)
team)
https://dzone.com/articles/spring-31-caching-and 6/6