Caching Java method results
Annotate your methods with @Cacheable
annotation and their responses will be cached (duplicate calculations will be avoided):
public class Resource { @Cacheable(lifetime = 5, unit = TimeUnit.SECONDS) public String load(URL url) { return url.openConnection().getContent(); } }
If you call this method, say, every second, only every 5th call will make a real HTTP connection. The other four will return a cached value. Cache is maintained in a concurrent hash map in memory. (Everything is thread safe).
You can make a value cacheable forever. (The method's result will never expire):
public class MyResource { @Cacheable(forever = true) public List<String> data() { List<String> data = new ArrayList<String>(); // some heavy calculations are to be done only // once per JVM lifetime. return data; } }
If a method throws an exception, it is not cached.
Since version 0.7.14, you can also annotate methods that should flush the object's cache.
Since 0.7.18, you can flush before or after the call using @Cacheable.FlushBefore
and @Cacheable.FlushAfter
. For example:
public class Page { @Cacheable public String get() { // Load data from the external source; e.g. the network return data. } @Cacheable.FlushBefore public void set(String data) { // Save data to the network. } }
Be aware of a potential problem with the caching of mutable objects. For example, if a method returns a HashSet
and then you change it, a new call to the same method will return a modified set, instead of the one originally cached. We strongly recommend to make sure that you cache only immutable objects.
public class Employees { @Cacheable public Set<Employee> all() { Set<Employee> employees = new HashSet<Employee>(); // Pay attention to the use of unmodifiableSet() which // turns a mutable HashSet into an immutable one. return Collections.unmodifiableSet(employees); } }
If you need a more fine-tunable mechanism, we recommend to use Google Guava. Also, pay attention to JSR-107 which is a new coming Java caching standard.
The mechanism is implemented with AOP/AspectJ. Read to integrate it into your pom.xml
.
This blog post gives more information about the internal details of this mechanism.