Spring 3.1 Caching and @Cacheable
Join the DZone community and get the full member experience.
Join For FreeCaches 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 difficulties 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 applied at type level, then the return value of every method is cached.
@Cacheable(value = "employee")
public class EmployeeDAO {
public Person findEmployee(String firstName, String surname, int age) {
return new Person(firstName, surname, age);
}
public Person findAnotherEmployee(String firstName, String surname, int age) {
return new Person(firstName, surname, age);
}
}
@Cacheable(value = "employee")
public Person findEmployee(String firstName, String surname, int age) {
return new Person(firstName, surname, age);
}
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 define a custom key you use a SpEL expression.
@Cacheable(value = "employee", key = "#surname")
public Person findEmployeeBySurname(String firstName, String surname, int age) {
return new Person(firstName, surname, age);
}
The final @Cacheable argument is the optional condition argument. Again, this references a SpEL expression, but this time it’s specifies a condition that’s used to determine whether or not your method’s return value is added to the cache.
@Cacheable(value = "employee", condition = "#age < 25")
public Person findEmployeeByAge(String firstName, String surname, int age) {
return new Person(firstName, surname, age);
}
Having quickly demonstrated how to apply some caching, the next thing to do is to take a look at what it all means.
@Test
public void testCache() {
Person employee1 = instance.findEmployee("John", "Smith", 22);
Person employee2 = instance.findEmployee("John", "Smith", 22);
assertEquals(employee1, employee2);
}
@Test
public void testCacheWithAgeAsCondition() {
Person employee1 = instance.findEmployeeByAge("John", "Smith", 22);
Person employee2 = instance.findEmployeeByAge("John", "Smith", 22);
assertEquals(employee1, employee2);
}
s employee2, which means that the following is true:
assertEquals(employee1, employee2);
@Test
public void testCacheOnSurnameAsKey() {
Person employee1 = instance.findEmployeeBySurname("John", "Smith", 22);
Person employee2 = instance.findEmployeeBySurname("Jack", "Smith", 55);
assertEquals(employee1, employee2);
}
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.
@Test
public void testCacheWithAgeAsCondition() {
Person employee1 = instance.findEmployeeByAge("John", "Smith", 22);
Person employee2 = instance.findEmployeeByAge("John", "Smith", 22);
assertEquals(employee1, employee2);
}
@Test
public void testCacheWithAgeAsCondition2() {
Person employee1 = instance.findEmployeeByAge("John", "Smith", 30);
Person employee2 = instance.findEmployeeByAge("John", "Smith", 30);
assertFalse(employee1 == employee2);
}
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 config 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.
Opinions expressed by DZone contributors are their own.
Comments