Caching in Java using Spring cache decoupling Services

Source: Internet
Author: User
Tags aop generator redis valid xml attribute xmlns

Although the previous way to implement caching, is defined by the cache operation interface, you can flexibly implement different caching, but after all, the energy is limited, to complete a different cache implementation is also a problem. What's more, code that has a lot of caching in the business code is too coupling to look elegant.
So, take the time to find out about other implementation scenarios. This is not, spring3.1 started, support based on the annotation of the cache, is the current I am more acceptable to a solution. After you finish your study, make a note.
Spring Cache is a set of annotations-based caching techniques that are not specifically implemented, but are implemented by default for Concurrentmap and Ehcache implementations. Of course, it also supports other caches.
What are the features of spring cache:
1. Annotation annotations with a small amount of configuration allows the existing code to support caching (very time-saving development time)
2. Support for out-of-the-box Out-of-the-box, that is, you can use caching without installing and deploying additional third-party components (in the Spring-context package, the Spring Web project will refer to this package)
3. Supports Spring Express Language, which can use any of the object's properties or methods to define the cached key and condition (support spel syntax)
4. Support AspectJ, and through its implementation of any method of caching support (the default based on the AOP solution, the adoption of AspectJ will be more flexible, described below)
5. Support for custom key and custom cache manager, with considerable flexibility and scalability (if Spel is not up to your expectations, be brave enough to realize your keygenerator)
6. Support a variety of cache implementations, default is based on CONCURRENTMAP implementation of the Concurrentmapcache, while supporting Ehcache implementation. To use cache such as Redis, you can introduce a REDIS implementation package.
What regrets do you have? In my consideration of the scene, there are some of the following regrets:
1. TTL is not supported, which means that expires time cannot be set. This is very regrettable, spring-cache that this is the cache to achieve their own things to do, there are solutions but only set the uniform expiration time, this is obviously not flexible. For example, the user's lottery number, validity, and other business, the day is valid, or 3 days, a week is valid, we tend to set the cache expiration time to solve this problem, and Spring-cache can not be completed.
2. Cannot generate cache key based on content in query result, such as GetUser (UID) method, want to pass query out of User.email generate cache key cannot realize.
3. Debugging Up Trouble
Stick with the previous code and see how it was done before:
/**
* Take cache first. If not, take it from DB, then save the cache
*/
@Override
Public userdetail getuserdetail (int userId) {
result<string> info = cachemanager.get (ucconstants.namespace,
Ucutil.getkey (Ucconstants.user_detail_uid_key, userId));
if (Stringutils.isnotempty (Info.getentity ())) {
Userdetail Userdetail = Jsonutils.fromjson (Info.getentity (), userdetail.class);
if (null!= userdetail) {
return userdetail;
}
}
Userdetail Userdetail = Userdetaildao.getuserdetail (userId);
if (userdetail!= null) {
if (logger.isdebugenabled ()) {
Logger.info ("Getuserdetail from DB userdetail=" + userdetail.tostring ());
}
Addtocache (Userdetail);
return userdetail;
}
return null;
}
private void Addtocache (Userdetail userdetail) {
Cachemanager.put (Ucconstants.namespace,
Ucutil.getkey (Ucconstants.user_detail_uid_key, Userdetail.getid ()),
Jsonutils.tojson (Userdetail), ucconstants.user_detail_cache_time);
Save space, save ID bar. Check it out once more.
Cachemanager.put (Ucconstants.namespace,
Ucutil.getkey (Ucconstants.user_detail_name_key, Userdetail.getusernickname ()),
Userdetail.getid () + "", ucconstants.user_detail_cache_time);
}
What does the code say after the annotation-driven Spring-cache:
@Cacheable (key= "#uid", value = "Usercache")
Public userdetail getuserdetail (int uid) {
return Userdetailmapper.getuser (UID);
}
Of course, the previous code has written two cache keys, which can be achieved by @caching annotations, as follows:
@Caching
(evict={@CacheEvict (value= "Usercache", key= "#user. UID"),
@CacheEvict (value= "Usercache", key= "#user. Email")})
Read the above code, that the note-driven cache is not very enjoyable? Introduction to code, low coupling. is simply the gospel of the vast program of apes. It's pretty easy to write code like the above. Let's start from the beginning.
Come on, let's get the configuration started. Spring is a bad thing and you have to configure everything. But it is also based on the configuration + annotation way, so that we are separated from the constant to new objects of the abyss of misery.
My cache is not going to use concurrentmapcache, so I'll just take ehcache as an example. Before using Ehcache, we need to introduce Ehcache packages and configure Ehcache.xml files.
Of course, in the production environment online, it is not recommended to use only ehcache this way. Can be used Ehcache+redis, or redis of the scheme can be.
MAVEN's Pom.xml file configuration:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.9</version>
</dependency>
Ehcache configuration, located under classpath ehcache.xml file:
<?xml version= "1.0" encoding= "UTF-8"?>
<ehcache xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"
xsi:nonamespaceschemalocation= "Http://ehcache.org/ehcache.xsd" updatecheck= "false" >
<diskstore path= "D:/cache"/> <!--Cache storage directory (this directory is placed in the system default cache directory), or "D:/cache" Java.io.tmpdir-->
<defaultcache
Maxelementsinmemory= "10000"
Eternal= "false"
Timetoidleseconds= "120"
Timetoliveseconds= "120"
Overflowtodisk= "true"
maxelementsondisk= "10000000"
Diskpersistent= "true"
Diskexpirythreadintervalseconds= "120"
Memorystoreevictionpolicy= "LRU"
/>
<cache name= "Usercache"
Maxelementsinmemory= "10000"
Eternal= "false"
Timetoidleseconds= "120"
Timetoliveseconds= "120"
Overflowtodisk= "true"
maxelementsondisk= "10000000"
Diskpersistent= "true"
Diskexpirythreadintervalseconds= "120"
Memorystoreevictionpolicy= "LRU"
/>
</ehcache>
Here explains, why two cache, with a bad?
My earliest time was a defaultcache, no usercache. It was later found that the Spring-cache configuration Ehcachecachemanager always failed to load, reporting errors:
Loadcaches must not return a empty Collection
I wonder, is there a defaultcache? So I tracked the code in the Abstractcachemanager source code of the Afterpropertiesset method has the following:
public void Afterpropertiesset () {
collection<? Extends cache> caches = loadcaches ();
Assert.notempty (Caches, "loadcaches must not return a empty Collection");
This.cacheMap.clear ();
Preserve the initial order of the cache names
for (Cache cache:caches) {
This.cacheMap.put (Cache.getname (), cache);
This.cacheNames.add (Cache.getname ());
}
}
The caches here is empty!. I really don't know why. I was trying to add a cache configuration named default, the results Ehcache and error, prompted already known as the cache of default. The name is changed to Usercache and the problem is resolved.
From the Ehcache error, Ehcache should be configured with a cache named default, but do not know why Spring-cache do not recognize. Know the classmate can tell me.
After configuring the Ehcache, it's time to configure our Spring-cache, and in order to facilitate management, I tend to configure separate spring-cache.xml files in the spring configuration directory. The contents are as follows:
<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"
xmlns:p= "http://www.springframework.org/schema/p"
Xsi:schemalocation= "Http://www.springframework.org/schema/beans
Http://www.springframework.org/schema/beans/spring-beans.xsd
Http://www.springframework.org/schema/cache
Http://www.springframework.org/schema/cache/spring-cache.xsd ">
<cache:annotation-driven cache-manager= "Ehcachemanager"/>
<!--Cache Properties-->
<bean id= "Ehcachemanagerfactory" class= "Org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
<property name= "configlocation" value= "Classpath:ehcache.xml"/>
</bean>
<!--generic Cache manager-->
<bean id= "Ehcachemanager" class= "Org.springframework.cache.ehcache.EhCacheCacheManager" >
<property name= "CacheManager" ref= "Ehcachemanagerfactory"/>
</bean>
</beans>
Of course, if you want to have no caching in the environment without any changes in the code (such as environmental migration, temporary testing, etc.), you can simply switch, that is OK.
Or, your environment has both ehcache, Redis, and Concurrentmapcache, which is also possible.
The highlight above, you can use Compositecachemanager to complete.
The following cachemanager need to be reconfigured:
<bean id= "CacheManager" class= "Org.springframework.cache.support.CompositeCacheManager" >
<property name= "Cachemanagers" >
<list>
<ref bean= "Ehcachemanager"/>
<ref bean= "Othercachamanager"/>
</list>
</property>
<property name= "Fallbacktonoopcache" value= "true"/>
</bean>
The Fallbacktonoopcache parameter determines what happens when there is no cachhe. If true, the cache is ignored directly, possibly into a DB query, and if False (the default is False), an exception is thrown when there is no caching:
Cannot find cache named [Usercache] for Cacheableoperation

Well done, then it's time to do the right thing. The use of Spring-cache is very simple, only a few simple annotations can be used. So what are the annotations? Look at the following table:



























Spring Cache Configuration

JSR-107 specification

Describe

@Cacheable

@CacheResult

The result returned by the caching method has three parameters, namely value (cache name), key (cache key), condition (cache condition)

@CachePut

@CachePut

The result returned by the cached method, and is executed when the method is invoked. Parameter with cacheable

@CacheEvict

@CacheRemove

Clears the cache. There are five parameters, in addition to the above 3, there are 2: allentries (whether all caches are cleared), beforeinvocation (whether to clear before the method call, the default is false, so when the method throws an exception the cache will not be erased)

@CacheEvict (Allentries=true)

@CacheRemoveAll

Clear all Caches

@CacheConfig

@CacheDefaults

There are some common configurations at the class level, such as value values, each method is the same, only need to be configured on the class once is good, this property is very useful, unfortunately spring3.1 not support.

To explain briefly, the above indicates the contents of the official document. On the left is the spring3.1 note about the cache operation, the middle is the annotation of the JSR-107 specification, spring is implemented in version 4.1, and the right is an explanation. I'm too lazy to translate.

The function and collocation method of each annotation also has the author to write is good, I took directly to use:




Introduction to @Cacheable, @CachePut, @CacheEvict annotations

With the above example, we can see that spring cache mainly uses two annotation tags, that is @Cacheable, @CachePut and @CacheEvict, we summarize its role and configuration methods.

Table 1. @Cacheable role and Configuration method




















the role of @Cacheable mainly for method configuration, can cache the result according to the request parameter of the method
@Cacheable the main parameters
Value The name of the cache, defined in the spring configuration file, must specify at least one For example:
@Cacheable (value= "Mycache") or
@Cacheable (value={"Cache1", "Cache2"}
Key Cached key, can be null, if specified to be written according to Spel expression, if not specified, the default is grouped by all parameters of the method For example:
@Cacheable (value= "Testcache", key= "#userName")
Condition Cached conditions, which can be null, write using Spel, return True or false, and cache only if True For example:
@Cacheable (value= "Testcache", condition= "#userName. Length () >2")

Table 2. @CachePut role and Configuration method




















the role of @CachePut mainly for the method configuration, can be based on the request parameters of the method to cache its results, and @Cacheable different, it will trigger the real method of the call every time
@CachePut the main parameters
Value The name of the cache, defined in the spring configuration file, must specify at least one For example:
@Cacheable (value= "Mycache") or
@Cacheable (value={"Cache1", "Cache2"}
Key Cached key, can be null, if specified to be written according to Spel expression, if not specified, the default is grouped by all parameters of the method For example:
@Cacheable (value= "Testcache", key= "#userName")
Condition Cached conditions, which can be null, write using Spel, return True or false, and cache only if True For example:
@Cacheable (value= "Testcache", condition= "#userName. Length () >2")

Table 3. @CacheEvict role and Configuration method




























the role of @CachEvict mainly for the method configuration, the cache can be emptied according to certain conditions
@CacheEvict the main parameters
Value The name of the cache, defined in the spring configuration file, must specify at least one For example:
@CachEvict (value= "Mycache") or
@CachEvict (value={"Cache1", "Cache2"}
Key Cached key, can be null, if specified to be written according to Spel expression, if not specified, the default is grouped by all parameters of the method For example:
@CachEvict (value= "Testcache", key= "#userName")
Condition The cached condition can be null, write with Spel, return True or FALSE, and only true to empty the cache For example:
@CachEvict (value= "Testcache",
Condition= "#userName. Length () >2")
Allentries Clears all cached content, defaults to False, and if specified as true, clears all caches immediately after the method call For example:
@CachEvict (value= "Testcache", Allentries=true)
Beforeinvocation Whether to empty before the method executes, the default is False, and if you specify true, empty the cache when the method has not yet been executed, by default, if the method throws an exception, the cache is not emptied For example:

@CachEvict (value= "Testcache", Beforeinvocation=true)



Regarding the above annotation function and the meaning, does not have the many supplementary explanation, the original author's article introduced also very detailed. Here to add spring-cache cache configuration. Cache element Configuration In addition to the Cache-manager property, there are many attributes, simply listed as follows:











































XML attribute

Annotation Properties

Default value

Meaning

Cache-manager

No

CacheManager

The default CacheManager name. A default cacheresolver is initialized in the background of the CacheManager, and a more granular management cache can be considered to set the Cache-resolver property

Cache-resolver

No

Simplecacheresolver

Cacheresolver's bean name, which is not a required attribute, but only as an alternative to the Cache-manager attribute

Key-generator

No

Simplekeygenerator

Custom Key Generator

Error-handler

No

Simplecacheerrorhandler

Custom Cache Error Handler, by default, exceptions are thrown directly to the client

Mode

Mode

Proxy

Spring Cache uses the spring's AOP framework by default to handle annotations by proxy, and another alternative is ASPECTJ. Cache annotations in spring AOP are not allowed to be invoked internally, so caching annotations can be invalidated when called internally, and AspectJ AOP solves this problem.

Proxy-target-class

Proxytargetclass

False

For proxy mode only, the annotation on the control class @cacheable or @cacheevict uses which caching agent. If the Proxy-target-class property is set to True, a proxy based on the class is created. If Proxy-target-class is false, a proxy based on the standard JDK interface is created. You can refer to AOP's Proxy-target-class properties specifically

order

order

Ord Ered. Lowest_precedence

determines the order of cache advice in the @cacheable or @cacheevict in the bean annotation, without specifying it means using an AOP decision Dvice order. The specific reference to a
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.