Starting with 3.1, spring introduced support for the cache. The methods and principles used are similar to spring's support for transaction management. Spring Cache is a method of action, and the core idea is that when we call a caching method, the method parameter and the return result are stored in the cache as a key-value pair, and the method is no longer executed the next time the same parameter is invoked. Instead, the results are returned directly from the cache. So when using the spring cache we have to make sure that our cached methods have the same return result for the same method parameters.
Using spring cache requires that we do two things:
N declares some methods to use the cache
n Configuring spring support for the cache
As with spring's support for transaction management, Spring's support for caches also has annotations-based and XML-based configurations. Let's take a look at the annotation-based approach first.
1 Annotation-based support
Spring provides us with several annotations to support the spring Cache. Its core is mainly @cacheable and @cacheevict. The method that uses the @cacheable tag is executed after the spring cache caches its return results, and the method that uses the @cacheevict tag removes some elements of the spring cache before or after the method executes. Let's take a look at some of the annotations provided by spring based annotations on cache support in detail. 1.1 @Cacheable
@Cacheable can be marked on a method or on a class. When tagged on a method means that the method is cached, and when tagged on a class It means that all methods of the class are cache-enabled. For a cache-enabled method, spring caches its return value after it is called, ensuring that the next time the same parameter is used to execute the method, the result can be obtained directly from the cache without having to execute the method again. Spring caches the return value of the method as a key-value pair, and the value is the return result of the method, and spring supports two strategies, the default policy and the custom policy, which are explained later. It is important to note that caching is not triggered when a caching-enabled method is invoked inside the object. @Cacheable can specify three properties, value, key, and condition. 1.1.1 The Value property specifies the cache name
The Value property must be specified, which means that the return value of the current method is cached on which cache, corresponding to the name of the cache. It can be a cache or multiple caches, which is an array when multiple caches need to be specified.
The @Cacheable ("cache1")//cache occurs on cache1.
Public User find (Integer ID) {
Returnnull;
}
The @Cacheable ({"Cache1", "Cache2"})//cache occur on cache1 and cache2
Public User find (Integer ID) {
Returnnull;
}
1.1.2 Using the key property to customize the key
The key property is used to specify the key that corresponds to the return result of the spring cache method. This property supports Springel expressions. When we do not specify this property, spring uses the default policy to generate the key. Let's take a look at the custom policy here, as the default policy is described separately later in this article.
The custom policy is that we can specify our key through the El expression of spring. The El expressions here can use the method parameters and their corresponding properties. We can use "#参数名" or "#p参数index" directly when using method parameters. Here are a few examples of using parameters as keys.
@Cacheable (value= "Users", key= "#id")
Public User find (Integer ID) {
Returnnull;
}
@Cacheable (value= "Users", key= "#p0")
Public User find (Integer ID) {
Returnnull;
}
@Cacheable (value= "Users", key= "#user. ID")
Public User find (user user) {
Returnnull;
}
@Cacheable (value= "Users", key= "#p0. ID")
Public User find (user user) {
Returnnull;
}
In addition to the above usage parameters as key, Spring also provides us with a root object that can be used to generate the key. The root object allows us to obtain the following information.
Property name |
Description |
Example |
MethodName |
Current method Name |
#root. MethodName |
Method |
Current method |
#root. Method.name |
Target |
The object that is currently being called |
#root. Target |
Targetclass |
The class of the object currently being called |
#root. Targetclass |
Args |
An array of current method parameters |
#root. Args[0] |
Caches |
The cache used by the currently invoked method |
#root. Caches[0].name |
We can also omit "#root" when we want to use the root object's property as key, because spring uses the root object's properties by default. Such as:
@Cacheable (value={"users", "XXX"}, key= "Caches[1].name")
Public User find (user user) {
Returnnull;
}
1.1.3 Condition property specifies the condition that occurs
Sometimes we may not want to cache a method with all of the returned results. This functionality can be achieved through the condition property. The Condition property defaults to NULL, which means that all invocation scenarios are cached. The value is specified by the Springel expression, which is true when the cache is processed, and when false indicates that no caching is processed, that method executes once each time the method is called. The following example indicates that caching occurs only if the ID of the user is even.
@Cacheable (value={"Users"}, key= "#user. Id", condition= "#user. id%2==0")
Public User find (user user) {
System.out.println ("Find User by user" + user);
return user;
}
1.2 @CachePut
In a spring cache-enabled environment, for a method that uses the @cacheable annotation, spring checks to see if there is a cache element of the same key in the cache before each execution, and if it does not execute the method, it returns the result directly from the cache. Otherwise it will execute and the returned result will be stored in the specified cache. @CachePut can also declare a method that supports caching functionality. Unlike @cacheable, a method that uses the @cacheput annotation does not check the cache for previous results before execution, but executes the method every time and deposits the execution result in the specified cache as a key-value pair.
@CachePut can also be labeled on the class and on the method. The properties we can specify when using @cacheput are the same as @cacheable.
@CachePut ("Users")//Executes the method each time and stores the result in the specified cache
Public User find (Integer ID) {
Returnnull;
}
1.3 @CacheEvict
The @CacheEvict is used to label the method or class on which the cache element needs to be cleared. When marked on a class, the execution of all the methods in it indicates that the cached purge operation is triggered. @CacheEvict properties that can be specified are value, key, condition, allentries, and Beforeinvocation. The semantics of value, key, and condition are similar to those of the @cacheable counterparts. That is, value indicates which cache (corresponding to the cache name) The purge operation occurred on, and key indicates which key needs to be purged, and key;condition generated using the default policy, if unspecified, represents the condition in which the purge operation occurs. Let's take a look at the new two properties Allentries and Beforeinvocation. 1.3.1 Allentries Properties
Allentries is a Boolean type that indicates whether all elements in the cache need to be cleared. The default is false, which means it is not required. When Allentries is specified as true, the Spring cache ignores the specified key. Sometimes we need the cache to clear all the elements, which is more efficient than a clear element.
@CacheEvict (value= "Users", allentries=true)
Public void Delete (Integer ID) {
System.out.println ("Delete User by ID:" + ID);
}
1.3.2 Beforeinvocation Properties
The purge operation is triggered by default after the corresponding method executes successfully, that is, the method does not trigger a purge operation if it fails to return successfully because it throws an exception. Using Beforeinvocation can change the time that the purge operation is triggered, and when we specify that the property value is true, spring clears the specified element in the cache before calling the method.
@CacheEvict (value= "Users", beforeinvocation=true)
Public void Delete (Integer ID) {
System.out.println ("Delete User by ID:" + ID);
}
In fact, in addition to using @cacheevict to clear the cache element, when we use Ehcache as the implementation, we can also configure the Ehcache own eviction policy, which is specified by the Ehcache configuration file. Since Ehcache is not the focus of this article, it's not a lot to go through here, and for more information about Ehcache, check out my column on Ehcache.
1.4 @Caching
@Caching annotations Allow us to specify multiple spring cache-related annotations at the same time on a method or class. It has three properties: cacheable, put, and evict, which are used to specify @cacheable, @CachePut, and @cacheevict, respectively.
@Caching (cacheable = @Cacheable ("Users"), evict = {@CacheEvict ("cache2"),
@CacheEvict (value = "Cache3", allentries = true)})
Public User find (Integer ID) {
Returnnull;
}
1.5 using custom annotations
Spring allows us to use custom annotations when configuring cacheable methods, provided that the corresponding annotations must be annotated on the custom annotations. If we have one of the following custom annotations that are annotated with @cacheable.
@Target ({elementtype.type, elementtype.method})
@Retention (Retentionpolicy.runtime)
@Cacheable (value= "users")
Public @interface mycacheable {
}
The same effect can be achieved by using @mycacheable on the method we need to cache.
@MyCacheable
Public User FindByID (Integer ID) {
System.out.println ("Find User by ID:" + ID);
User user = new user ();
User.setid (ID);
User.setname ("Name" + ID);
return user;
}
2 Configuring spring support for the cache 2.1 Declaring support for the cache 2.1.1 Based on annotations
To configure spring support for note-based caches, we first need to introduce the cache namespace in spring's configuration file, followed by <cache:annotation-driven/> You can enable spring support for note-based caches.
<?xml version= "1.0" encoding= "UTF-8"?>
<beans xmlns= "Http://www.springframework.org/schema/beans"
Xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"
Xmlns:cache= "Http://www.springframework.org/schema/cache"
Xsi:schemalocation= "Http://www.springframework.org/schema/beans
Http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
Http://www.springframework.org/schema/cache
Http://www.springframework.org/schema/cache/spring-cache.xsd ">
<cache:annotation-driven/>
</beans>
<cache:annotation-driven/> has a Cache-manager property to specify the name of the bean that is currently used by the CacheManager, which is CacheManager by default. So when our CacheManager ID is CacheManager We can not specify this parameter, otherwise we need to specify.
<cache:annotation-driven/> can also specify a mode property, and the optional values are proxy and ASPECTJ. The default is to use proxy. When mode is proxy, the spring cache does not function until the cache method is called externally, which means that the spring cache does not work if a cache method is invoked within its declared object. There is no such problem when mode is ASPECTJ. When using proxy, only annotations such as @cacheable on the public method will work, and if you need a method on a non-public method, you can also set mode to ASPECTJ when using spring cache.
In addition,,<cache:annotation-driven/> can also specify a Proxy-target-class property that indicates whether to proxy class and false by default. The @cacheable, @cacheEvict, etc. we mentioned earlier can also be labeled on the interface, which is not a problem for interface-based proxies. However, it is important to note that when we set Proxy-target-class to TRUE or mode to ASPECTJ, it is directly based on class, and the cache annotations defined on the interface are not recognized, and the corresponding spring The cache won't work either.
It is important to note that <cache:annotation-driven/> will only look for cache annotations that are defined under the same ApplicationContext @cacheable.
2.1.2 Based on XML configuration
In addition to using annotations to declare support for the cache, spring also supports the use of XML to declare support for the cache. This is mainly done through cache:advice similar to the Aop:advice. A cache:advice element is defined under the cache namespace to define a advice for the cache. It needs to specify a Cache-manager property, which defaults to CacheManager. Cache:advice you can specify more than one cache:caching element, which is somewhat similar to the @caching annotation when using annotations. The cache:cacheable, Cache:cache-put, and cache:cache-evict elements can be specified under the Cache:caching element, similar to the @cacheable when using annotations, @ Cacheput and @cacheevict. Let's look at an example:
<cache:adviceid= "Cacheadvice" cache-manager= "CacheManager" >
<cache:cachingcache= "Users" >
<cache:cacheablemethod= "FindByID" key= "#p0"/>
<cache:cacheablemethod= "Find" key= "#user. Id"/>
<cache:cache-evictmethod= "DeleteAll" all-entries= "true"/>
</cache:caching>
</cache:advice>
The above configuration defines a cache:advice named Cacheadvice that specifies the cache FindByID method and the Find method to the cache named users. The method here can also use the wildcard character "*", such as "find*" for any method that starts with "find".
With Cache:advice, we also need to introduce an AOP namespace, and then aop:config specify which pointcut to apply to the defined Cacheadvice. Such as:
<aop:configproxy-target-class= "false" >
<aop:advisoradvice-ref= "Cacheadvice" pointcut= "Execution (* com.xxx.userservice.* (..))" />
</aop:config>
The above configuration indicates that the cacheadvice corresponding Cache:advice will be used for spring cache processing when any public method in the Com.xxx.UserService is called. More about Spring AOP is not within the scope of this article.
2.2 Configuring CacheManager
CacheManager is a spring-defined interface for managing the cache. Spring itself has provided us with two CacheManager implementations, one based on the Java API Concurrentmap and the other based on the third-party cache implementation--ehcache, if we need to use other types of caches, We can implement spring's CacheManager interface or Abstractcachemanager abstract class on our own. Here's a look at the two CacheManager configuration examples that spring has done for us. 2.2.1 Concurrentmap-based configuration
<bean id= "CacheManager" class= "Org.springframework.cache.support.SimpleCacheManager" >
<propertyname= "Caches" >
<set>
<beanclass= "Org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name= "xxx"/>
</set>
</property>
</bean>
The above configuration uses a Simplecachemanager, which contains a concurrentmapcache named "xxx".
2.2.2 Ehcache-based configuration
<!--Ehcache Realized--
<bean id= "CacheManager" class= "Org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref= " Ehcachemanager "/>
<bean id= "Ehcachemanager" class= "Org.springframework.cache.ehcache.EhCacheManagerFactoryBean" P: config-location= "Ehcache-spring.xml"/>
The above configuration uses a spring-provided ehcachecachemanager to generate a spring CacheManager that receives a ehcache CacheManager, Because it's ehcache to actually cache the data. The CacheManager of Ehcache is generated through the Ehcachemanagerfactorybean provided by spring, which can generate a Ehcache CacheManager by specifying the location of the Ehcache configuration file. If not specified, the Ehcache.xml file under the Classpath root path will be taken according to the default rule of Ehcache, and if the file does not exist, obtain the Ehcache-failsafe.xml file in the Ehcache corresponding jar package as the configuration file. More about Ehcache here is not much to say, it does not belong to the content of this article, to learn more about Ehcache can refer to my previous release of the Ehcache series of articles, can also refer to official documents.
3-Key generation strategy
There are two kinds of key generation strategies, one is the default policy and one is a custom policy. 3.1 Default Policy
The default key generation policy is generated by Keygenerator with the following default policy:
N If the method has no arguments, use 0 as the key.
n Use this parameter as key if there is only one argument.
n If the argument is extra, use the hashcode of all parameters as key.
If we need to specify our own default policy, then we can implement our own keygenerator and then specify the keygenerator that our spring cache uses to define our own keygenerator.
When using annotation-based configuration, it is specified by Cache:annotation-driven.
<cache:annotation-drivenkey-generator= "Userkeygenerator"/>
<bean id= "Userkeygenerator" class= "Com.xxx.cache.UserKeyGenerator"/>
The use of XML-based configuration is specified by Cache:advice.
<cache:adviceid= "Cacheadvice" cache-manager= "CacheManager" key-generator= "Userkeygenerator" >
</cache:advice>
It is important to note that the default generation strategy for all of the keys we use at this time is the same keygenerator. 3.2 Custom Policies
The custom policy is that we can specify our key through the El expression of spring. The El expressions here can use the method parameters and their corresponding properties. We can use "#参数名" or "#p参数index" directly when using method parameters. Here are a few examples of using parameters as keys.
@Cacheable (value= "Users", key= "#id")
Public User find (Integer ID) {
Returnnull;
}
@Cacheable (value= "Users", key= "#p0")
Public User find (Integer ID) {
Returnnull;
}
@Cacheable (value= "Users", key= "#user. ID")
Public User find (user user) {
Returnnull;
}
@Cacheable (value= "Users", key= "#p0. ID")
Public User find (user user) {
Returnnull;
}
In addition to the above usage parameters as key, Spring also provides us with a root object that can be used to generate the key. The root object allows us to obtain the following information.
Property name |
Description |
Example |
MethodName |
Current method Name |
#root. MethodName |
Method |
Current method |
#root. Method.name |
Target |
The object that is currently being called |
#root. Target |
Targetclass |
The class of the object currently being called |
#root. Targetclass |
Args |
An array of current method parameters |
#root. Args[0] |
Caches |
The cache used by the currently invoked method |
#root. Caches[0].name |
We can also omit "#root" when we want to use the root object's property as key, because spring uses the root object's properties by default. Such as:
@Cacheable (value={"users", "XXX"}, key= "Caches[1].name")
Public User find (user user) {
Returnnull;
}
4 Spring uses ehcache alone
What was described earlier is spring's built-in support for the cache, but we can also use spring's own Ehcache CacheManager or Ehcache objects alone. By configuring Ehcachemanagerfactorybean and Ehcachefactorybean in the application context, We can then inject the corresponding Ehcache CacheManager and Ehcache objects into other spring bean objects for use.
4.1 Ehcachemanagerfactorybean
Ehcachemanagerfactorybean is a factorybean of spring built-in CacheManager objects that can produce ehcache. It is possible to specify the path to the Ehcache configuration file used to create CacheManager through the property configlocation, usually the path of the Ehcache.xml file. If configlocation is not specified, the CacheManager is created using the default location profile, which is the logic that belongs to Ehcache itself. That is, if a ehcache.xml file exists under the Classpath root path, the file is used directly as the Ehcache configuration file, otherwise the Ehcache-failsafe.xml file in Ehcache-xxx.jar is used as the configuration file