From 4e90c0a81f260a9e9264b69a6722ed37cec1e866 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Mon, 27 Dec 2010 18:36:57 +0000 Subject: [PATCH] SPR-7308 + wrapping up cache documentation + plug in cache docs git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3832 50f2f4bb-b051-0410-bef5-90022cba6387 --- spring-framework-reference/src/cache.xml | 243 +++++++++++++++++- .../src/spring-framework-reference.xml | 4 - 2 files changed, 236 insertions(+), 11 deletions(-) diff --git a/spring-framework-reference/src/cache.xml b/spring-framework-reference/src/cache.xml index a3cae6ff2e9..16280476c20 100644 --- a/spring-framework-reference/src/cache.xml +++ b/spring-framework-reference/src/cache.xml @@ -128,13 +128,24 @@ 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) - +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. -
+
+ Conditional caching + + Sometimes, a method might not be suitable for caching all the time (for example, it might depend on the given arguments). The cache annotations support such functionality + through the conditional parameter which takes a SpEL expression that is evaluated to either true or false. + If true, the method is cached - if not, it behaves as if the method is not cached, that is executed every since time no matter what values are in the cache or what + arguments are used. A quick example - the following method will be cached, only if the argument name has a length shorter then 32: + + +
+ +
Available caching <literal>SpEL</literal> evaluation context Each SpEL expression evaluates again a dedicated context. In addition @@ -181,18 +192,236 @@ public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
+ <literal>@CacheEvict</literal> annotation + + The cache abstraction allows not just population of a cache store but also eviction. This process is useful for removing stale or unused data from the cache. Opposed to + @Cacheable, annotation @CacheEvict demarcates methods that perform cache eviction, that is methods that act as triggers + for removing data from the cache. Just like its sibling, @CacheEvict requires one to specify one (or multiple) caches that are affected by the action, allows a + key or a condition to be specified but in addition, features an extra parameter allEntries which indicates whether a cache-wide eviction needs to be performed + rather then just an entry one (based on the key): + + + + This option comes in handy when an entire cache region needs to be cleared out - rather then evicting each entry (which would take a long time since it is inefficient), + all the entires are removed in one operation as shown above. Note that the framework will ignore any key specified in this scenario as it does not apply (the entire cache is evicted not just + one entry). + + It is important to note that void methods can be used with @CacheEvict - as the methods act as triggers, the return values are ignored (as they don't interact with + the cache) - this is not the case with @Cacheable which adds/update data into the cache and thus requires a result. +
+
+ Enable caching annotations + + It is important to note that even though declaring the cache annotations does not automatically triggers their actions - like many things in Spring, the feature has to be declaratively + enabled (which means if you ever suspect caching is to blame, you can disable it by removing only one configuration line rather then all the annotations in your code). In practice, this + translates to one line that informs Spring that it should process the cache annotations, namely: + + + xmlns:cache="http://www.springframework.org/schema/cache"http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd]]> + ]]> + + The namespace allows various options to be specified that influence the way the caching behaviour is added to the application through AOP. The configuration is similar (on purpose) + with that of tx:annotation-driven: + + + + <literal><cache:annotation-driven/></literal> + settings + + + + + Attribute + + Default + + Description + + + + + + cache-manager + + cacheManager + + Name of cache manager to use. Only required + if the name of the cache manager is not + cacheManager, as in the example + above. + + + + mode + + proxy + + The default mode "proxy" processes annotated + beans to be proxied using Spring's AOP framework (following + proxy semantics, as discussed above, applying to method calls + coming in through the proxy only). The alternative mode + "aspectj" instead weaves the affected classes with Spring's + AspectJ transaction aspect, modifying the target class byte + code to apply to any kind of method call. AspectJ weaving + requires spring-aspects.jar in the classpath as well as + load-time weaving (or compile-time weaving) enabled. (See + for details on how to set + up load-time weaving.) + + + + proxy-target-class + + false + + Applies to proxy mode only. Controls what type of + transactional proxies are created for classes annotated with + the @Cacheable or @CacheEvict annotations. + If the proxy-target-class attribute is set + to true, then class-based proxies are + created. If proxy-target-class is + false or if the attribute is omitted, then + standard JDK interface-based proxies are created. (See for a detailed examination of the + different proxy types.) + + + + order + + Ordered.LOWEST_PRECEDENCE + + Defines the order of the cache advice that + is applied to beans annotated with + @Cacheable or @CacheEvict. + (For more + information about the rules related to ordering of AOP advice, + see .) No + specified ordering means that the AOP subsystem determines the + order of the advice. + + + +
+ + + The proxy-target-class attribute on the + <cache:annotation-driven/> element controls what + type of caching proxies are created for classes annotated with + the @Cacheable/@CacheEvict annotation. If + proxy-target-class attribute is set to + true, class-based proxies are created. If + proxy-target-class is false or + if the attribute is omitted, standard JDK interface-based proxies are + created. (See for a discussion of the + different proxy types.) + + + + <cache:annotation-driven/> only looks for + @Cacheable/@CacheEvict on beans in the same + application context it is defined in. This means that, if you put + <cache:annotation-driven/> in a + WebApplicationContext for a + DispatcherServlet, it only checks for + @Cacheable/@CacheEvict beans in your + controllers, and not your services. See for more information. + + +
+ +
+ Using custom annotations + + The caching abstraction allows one to use her own annotations to identify what method trigger cache population or eviction. This is quite handy as a template mechanism as it eliminates + the need to duplicate cache annotation declarations (especially useful if the key or condition are specified) or if the foreign imports (org.springframework) are not allowed + in your code base. Similar to the rest of the stereotype annotations, both @Cacheable and @CacheEvict + can be used as meta-annotations, that is annotations that can annotate other annotations. To wit, let us replace a common @Cacheable declaration with our own, custom + annotation: + + + + + Above, we have defined our own SlowService annotation which itself is annotated with @Cacheable - now we can replace the following code: + + + + with: + + + + Even though @SlowService is not a Spring annotation, the container automatically picks up its declaration at runtime and understands its meaning. Note that as + mentined above, the annotation-driven behaviour needs to be enabled.
-
- Configuring the <interfacename>Cache</interfacename> - +
+ Configuring the cache storage + + Out of the box, the cache abstraction provides integration with two storages - one on top of the JDK ConcurrentMap and one + for ehcache library. To use them, one needs to simply declare an appropriate CacheManager - an entity that controls and manages + Caches and can be used to retrieve these for storage. + +
+ JDK <interfacename>ConcurrentMap</interfacename>-based <interfacename>Cache</interfacename> + + The JDK-based Cache implementation resides under org.springframework.cache.concurrent package. It allows one to use + ConcurrentHashMap as a backing Cache store. + + + + + + + + + +]]> + + The snippet above uses the SimpleCacheManager to create a CacheManager for the two, nested Concurrent + Cache implementations named default and books. + Note that the names are configured directly for each cache. + + As the cache is created by the application, it is bound to its lifecycle, making it suitable for basic use cases, tests or simple applications. The cache scales well and is very fast + but it does not provide any management or persistence capabilities nor eviction contracts. +
+ +
+ Ehcache-based <interfacename>Cache</interfacename> + + The Ehcache implementation is located under org.springframework.cache.ehcache package. Again, to use it, one simply needs to declare the appropriate + CacheManager: + + + + +]]> + + This setup bootstraps ehcache library inside Spring IoC (through bean ehcache) which is then wired into the dedicated CacheManager + implementation. Note the entire ehcache-specific configuration is read from the resource ehcache.xml. +
+
Plugging-in different back-end caches - + + Clearly there are plenty of caching products out there that can be used as a backing store. To plug them in, one needs to provide a CacheManager and + Cache implementation since unfortunately there is no available standard that we can use instead. This may sound harder then it is since in practice, + the classes tend to be simple adapters that map the caching abstraction framework on top of the storage API as the ehcache classes can show. + Most CacheManager classes can use the classes in org.springframework.cache.support package, such as AbstractCacheManager + which takes care of the boiler-plate code leaving only the actual mapping to be completed. We hope that in time, the libraries that provide integration with Spring + can fill in this small configuration gap.
\ 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 a3190059593..3fdf66a5285 100644 --- a/spring-framework-reference/src/spring-framework-reference.xml +++ b/spring-framework-reference/src/spring-framework-reference.xml @@ -454,11 +454,9 @@ - @@ -480,10 +478,8 @@ -