From c84ffae75c2c6a0f1dbcf4ad162e78b5026c476e Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Tue, 21 Dec 2010 17:13:17 +0000 Subject: [PATCH] SPR-7308 + draft cache documentation git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3829 50f2f4bb-b051-0410-bef5-90022cba6387 --- spring-framework-reference/src/cache.xml | 198 ++++++++++++++++++ .../src/spring-framework-reference.xml | 11 + 2 files changed, 209 insertions(+) create mode 100644 spring-framework-reference/src/cache.xml diff --git a/spring-framework-reference/src/cache.xml b/spring-framework-reference/src/cache.xml new file mode 100644 index 00000000000..a3cae6ff2e9 --- /dev/null +++ b/spring-framework-reference/src/cache.xml @@ -0,0 +1,198 @@ + + + + + Cache Abstraction + +
+ Introduction + + Since version 3.1, Spring Framework provides support for transparently + adding caching into an existing Spring application. Similar to the transaction + support, the caching abstraction allows consistent use of various caching + solutions with minimal impact on the code. +
+ +
+ Understanding the cache abstraction + + + Cache vs Buffer + The terms "buffer" and "cache" tend to be used interchangeably; note however they represent different things. + A buffer is used traditionally as an intermediate temporary store for data between a fast and a slow entity. As one + party would have to wait for the other affecting performance, the buffer alleviates this by + allowing entire blocks of data to move at once rather then in small chunks. The data is written and read only once from + the buffer. Further more, the buffers are visible to at least one party which is aware of it. + A cache on the other hand by definition is hidden and neither party is aware that caching occurs.It as well improves + performance but does that by allowing the same data to be read multiple times in a fast fashion. + + A further explanation of the differences between two can be found + here. + + + At its core, the abstraction applies caching to Java methods, reducing thus the number of executions based on the + information available in the cache. That is, each time a targeted method is invoked, the abstraction + will apply a caching behaviour checking whether the method has been already executed for the given arguments. If it has, + then the cached result is returned without having to execute the actual method; if it has not, then method is executed, the + result cached and returned to the user so that, the next time the method is invoked, the cached result is returned. + This way, expensive methods (whether CPU or IO bound) can be executed only once for a given set of parameters and the result + reused without having to actually execute the method again. The caching logic is applied transparently without any interference + to the invoker. + + Obviously this approach works only for methods that are guaranteed to return the same output (result) for a given input + (or arguments) no matter how many times it is being executed. + + To use the cache abstraction, the developer needs to take care of two aspects: + + caching declaration - identify the methods that need to be cached and their policy + cache configuration - the backing cache where the data is stored and read from + + + + Note that just like other services in Spring Framework, the caching service is an abstraction (not a cache implementation) and requires + the use of an actual storage to store the cache data - that is, the abstraction frees the developer from having to write the caching + logic but does not provide the actual stores. There are two integrations available out of the box, for JDK java.util.concurrent.ConcurrentMap + and Ehcache - see for more information on plugging in other cache stores/providers. +
+ +
+ Declarative annotation-based caching + + For caching declaration, the abstraction provides two Java annotations: @Cacheable and @CacheEvict which allow methods + to trigger cache population or cache eviction. Let us take a closer look at each annotation: + +
+ <literal>@Cacheable</literal> annotation + + As the name implies, @Cacheable is used to demarcate methods that are cacheable - that is, methods for whom the result is stored into the cache + so on subsequent invocations (with the same arguments), the value in the cache is returned without having to actually execute the method. In its simplest form, + the annotation declaration requires the name of the cache associated with the annotated method: + + + + In the snippet above, the method findBook is associated with the cache named books. Each time the method is called, the cache + is checked to see whether the invocation has been already executed and does not have to be repeated. While in most cases, only one cache is declared, the annotation allows multiple + names to be specified so that more then one cache are being used. In this case, each of the caches will be checked before executing the method - if at least one cache is hit, + then the associated value will be returned: + All the other caches that do not contain the method will be updated as well event though the cached method was not actually + executed. + + + +
+ Default Key Generation + + Since caches are essentially key-value stores, each invocation of a cached method needs to be translated into a suitable key for cache access. + Out of the box, the caching abstraction uses a simple hash-code based KeyGenerator that computes the key based on the + hashes of all objects used for method invocation. This approach works well for objects with natural keys as long as + the hashCode() reflects that. If that is not the case then + for distributed or persistent environments, the strategy needs to be changed as the objects hashCode is not preserved. + In fact, depending on the JVM implementation or running conditions, the same hashCode can be reused for different objects, in the same VM instance. + + To provide a different default key generator, one needs to implement the org.springframework.cache.KeyGenerator interface. + Once configured, the generator will be used for each declaration that doesn not specify its own key generation strategy (see below). + +
+ +
+ Custom Key Generation Declaration + + Since caching is generic, it is quite likely the target methods have various signatures that cannot be simply mapped on top of the cache structure. This tends to become + obvious when the target method has multiple arguments out of which only some are suitable for caching (while the rest are used only by the method logic). For example: + + + + At first glance, while the two boolean arguments influence the way the book is found, they are no use for the cache. Further more what if only one of the two + is important while the other is not? + + For such cases, the @Cacheable annotation allows the user to specify how the key is generated through its key attribute. + The developer can use SpEL to pick the arguments of interest (or their nested properties), perform operations or even invoke arbitrary methods without + having to write any code or implement any interface. This is the recommended approach over the default generator since + methods tend to be quite different in signatures as the code base grows; while the default strategy might work for some methods, it rarely does for all methods. + + + Below are some examples of various SpEL declarations - if you are not familiar with it, do yourself a favour and read : + + + +@Cacheable(value="book", key="isbn" +public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) + + +@Cacheable(value="book", key="isbn.rawNumber") +public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) + + +@Cacheable(value="book", key="T(someType).hash(isbn)") +public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) + + + The snippets above, show how easy it is to select a certain argument, one of its properties or even an arbitrary (static) method. +
+ +
+ Available caching <literal>SpEL</literal> evaluation context + + Each SpEL expression evaluates again a dedicated context. In addition + to the build in parameters, the framework provides dedicated caching related metadata such as the argument names. The next table lists the items made available to the context + so one can use them for key and conditional(see next section) computations: + + + Cache SpEL available metadata + + + + + Name + Location + Description + Example + + + + + methodName + root object + The name of the method being invoked + #root.methodName + + + caches + root object + Collection of caches against which the current method is executed + #root.caches[0].name + + + parameter name + evaluation context + Name of any of the method parameter. If for some reason the names are not available (ex: no debug information), + the parameter names are also available under the ]]> where + stands for the parameter index (starting from 0). + iban or p0 + + + +
+
+
+ +
+ +
+
+ +
+ Configuring the <interfacename>Cache</interfacename> + +
+ +
+ Plugging-in different back-end caches + +
+ +
\ No newline at end of file diff --git a/spring-framework-reference/src/spring-framework-reference.xml b/spring-framework-reference/src/spring-framework-reference.xml index 29001e840a7..a3190059593 100644 --- a/spring-framework-reference/src/spring-framework-reference.xml +++ b/spring-framework-reference/src/spring-framework-reference.xml @@ -453,6 +453,12 @@ + + @@ -473,6 +479,11 @@ + +