This article does not describe the installation and use of memcached, nor the long-winded cache framework for good performance. Instead, it is a combination of their own actual development, to talk about their own use.
One, configuration file Application-cache.xml
<?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:jee="/HTTP/ Www.springframework.org/schema/jee "xmlns:tx=" Http://www.springframework.org/schema/tx " xmlns:context=" Http://www.springframework.org/schema/context "xmlns:jdbc=" Http://www.springframework.org/schema/jdbc " xmlns:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" 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.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/ schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org /schema/jee/spring-jee-3.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/ Schema/aop/spring-aop-3.1.xsd http://www. springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/ spring-jdbc-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/ Schema/cache/spring-cache-3.1.xsd "default-lazy-init=" true "><!-- Caching service --><!-- Custom key generation strategy--><!-- <cache:annotation-driven key-generator= "Stringkeygenerator" /> <bean id= "Stringkeygenerator" class= "Cn.roomy.supply.metadata.cache.StringKeyGenerator" / > --><!--spring 3.1 introduced a note-based (annotation) caching (cache) technology --><cache: Annotation-driven cache-manager= "CacheManager" /><bean id= "CacheManager" class= " Cn.roomy.supply.metadata.cache.MemcacheCacheManager "> <!-- Whether transactions surround, if true, If the transaction is rolled back, the cache is rolled back, and the default false --> <p roperty name= "Transactionaware" value= "true" /><property name= "caches" ><set > <bean class= "Cn.roomy.supply.metadata.cache.MemcachedSpringCache" ><property name= "name" value= "R" /><property name= "Memcachedclient" ref= "Memcachedclient4user" /><!-- 1 days --><property name= "expiredduration" value= "86400" /></bean><bean class= "Cn.roomy.supply.metadata.cache.MemcachedSpringCache" ><property name= "name" value= "S" /><property name= "Memcachedclient" ref= "Memcachedclient4user" /><!-- 30 days --><property name= "Expiredduration" value= "2592000" /></bean><bean class= "Cn.roomy.supply.metadata.cache.MemcachedSpringCache" ><property name= "name" value= "V" /><prOperty name= "Memcachedclient" ref= "Memcachedclient4user" /><!-- 7 days -->< Property name= "Expiredduration" value= "604800" /></bean></set></property> </bean> <bean id= "MemcachedClient4User" class= "Net.spy.memcached.spring.MemcachedClientFactoryBean" > <property name= "Servers" value= "${memcached.url}"/> <!-- Specifies the protocol to use (Binary,text), which is text --> by default <property name= "Protocol" value= "TEXT"/> <!-- Set the default transcoding (default to Net.spy.memcached.transcoders.SerializingTranscoder) --> <property name= "Transcoder" > <bean class= "Net.spy.memcached.transcoders.SerializingTranscoder" > <property name= "CompressionThreshold " value="/> </bean> </property> <!-- Set the default operation time-out in milliseconds --> <property name= "Optimeout" value= "/> <property" name= "Timeoutexceptionthreshold" value= "19980"/> <!-- Set hash algorithm --> <property name= "HASHALG "> <value type=" Net.spy.memcached.DefaultHashAlgoRithm ">KETAMA_HASH</value> </property> <!-- Set Locator type (array_mod,consistent), default is Array_mod --> <property name= "Locatortype" value= "CONSISTENT"/ > <!-- Set failure mode (cancel, reassign, retry), default is reassign --> <property name= "Failuremode" value= "Redistribute" /> <!-- <property name= "Failuremode" value= "Retry"/> --> <!-- Set to True if you want to use the Nagle algorithm --> <property name= "UseNagleAlgorithm" Value= "false"/> &nbSp; </bean> </beans>
1. The configuration file has a key support cache configuration item: <cache:annotation-driven cache-manager= "CacheManager"/> This configuration item defaults to a name called CacheManager Cache Manager, we have customized a cache manager Memcachecachemanager, which needs to configure a property caches, which is a cache collection managed by this cache manager. The custom Memcachespringcache configures the effective time for each cache.
2, introduce the third party spy's client Mencacheclientfactorybean, set its related properties.
Second, Memcachecachemanager and Memcachespringcache
/* * copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the license. * you may obtain a copy of the license at * * http://www.apache.org/licenses/license-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the license is distributed on an "As is" basis, * without warranties or conditions of any kind, either express or implied. * see the license for the specific language governing permissions and * limitations under the license. */package cn.roomy.supply.metadata.cache;import java.util.collection;import org.springframework.cache.cache;import org.springframework.cache.transaction.abstracttransactionsupportingcachemanager;public class memcachecachemanager extends abstracttransactionsupportingcachemanager {public Memcachecachemanager () {}private Collection<? extends Cache> caches; /** * specify the collection of cache instances to use for this CacheManager. */ public void setcaches (collection<? extends cache> caches) { this.caches = caches; } @Override protected Collection<? extends Cache> loadcaches () { return this.caches; }}
here the emphasis on inheriting the Abstracttransactionsupportingcachemanager abstract class, see the class name probably also knows its main function, support for spring affairs! That is, if the transaction is rolled back, the cache data is removed. See its source, it inherits the Abstractcachemanager, and Abstractcachemanager realized the CacheManager interface.
package cn.roomy.supply.metadata.cache;import java.io.serializable;import java.util.concurrent.future;import java.util.concurrent.timeunit;import net.spy.memcached.memcachedclient;import org.apache.commons.lang3.time.stopwatch;import org.slf4j.logger;import org.slf4j.loggerfactory;import org.springframework.beans.factory.initializingbean;import org.springframework.cache.cache;import org.springframework.cache.support.simplevaluewrapper;import org.springframework.util.assert;/** * Memcached cache implementation based on Spring cache abstract system */public class memcachedspringcache implements Cache, InitializingBean {private final static Logger logger = Loggerfactory.getlogger (memcachedspringcache.class);p rivate string name;private memcachedclient memcachedClient;/** * default Maximum cache time is 1 hours */private static final int max_ expired_duration&The maximum cache time for the Nbsp;= 60 * 60;/** null value */private static final int null_ value_expiration = 60 * 60 * 24 * 7;/** increment expiration allows setting the maximum value */ private static final int delta_expiration_threshold = 60 * 60 * 24 * 30;/** * Cache Data Time-out time */private int expiredduration = max_ Expired_duration;private static final object null_holder = new nullholder () ;p rivate boolean allownullvalues = true; @Overridepublic void afterpropertiesset ( ) throws exception {assert.notnull (memcachedclient, "Memcachedclient must not be null! ");} @Overridepublic string getname () {return this.name;} @Overridepublic memcachedclient getnativecache () {return this.memcachedclient;} /** * is given a valuewrapper based on key and then calls its GEThe T method gets the value */@Overridepublic valuewrapper get (object key) {string cachekey = getcachekey (key); Try {stopwatch sw = new stopwatch (); Sw.start ();Object Value = memcachedclient.get (CacheKey); Sw.stop ();if (Sw.gettime () > 50) { Logger.info ("read memcached spents {}, key={}", sw.gettime (), cachekey);} return (Value != null ? new simplevaluewrapper (FromStoreValue (value)) : null);} catch (exception e) {logger.error ("read memcached cache exception, key={}, server={}", Cachekey,memcachedclient.getnodelocator (). Getprimary (CacheKey). Getsocketaddress (), e.getcause ()); return null;}} /** * Gets the value */@SuppressWarnings ("unchecked") directly based on the key, and the type of value @Overridepublic <t> t get (Object key, class<t> type) {ValueWrapper Element = get (key); Object value = (Element != null ? element.get () : null);if (value == null) return null;if (type != null && !type.isinstance (value)) {throw new illegalstateexception ("Cached value type specified error [" + type.getname () + "] : " + value);} return (T) value;} /** * is credited to the cached key and is threaded by the cached area +key object value * @param key key objects * @return */private string getcachekey (Object key) {return this.name + Key.tostring ();} /** * Store Data * Secure set method, return result in 3 seconds, otherwise cancel operation. */@Overridepublic void put ( Object key, object value) {string cachekey = getcachekey (key); Logger.debug ( "Put Cache key:{}, value:{}, storevalue:{}", cachekey, value, tostorevalue (Value)); int expiration = expiredDuration;if (value ==&Nbsp;null) {if (allownullvalues) {value = NULL_HOLDER; // If you allow null values to be cached, Null is substituted for the occupied pit object, and null is not allowed directly because}if (expiredduration > null_value_expiration) cannot be serialized { expiration = null_value_expiration; // shortens the expiration time for null values, with a maximum cache of 7 days}} else if ( Expiredduration > delta_expiration_threshold) {expiration += (int) ( System.currenttimemillis () / 1000); // modifies the expiration time of the UNIX timestamp type, enabling the ability to set an expiration time of more than 30 days// Note: Timestamp calculation There are 2038 problems,// 2038-1-19 11:14:07 (gmt +8) , the converted int will overflow, resulting in a negative value} Future<boolean> future = memcachedclient.set (cachekey, expiration, value); try {future.get (3, timeunit.seconds);} catch (Exception e) {future.cancel (false); Logger.error ("memcached write Cache exception, key={}, server={} ", cachekey,memcachedclient.getnodelocator (). Getprimary (CacheKey). Getsocketaddress (), e);}} /** * Remove the cache * secure evict method from the cache, and return the result, or cancel the operation within 3 seconds. */@Overridepublic void evict ( Object key) {string cachekey = getcachekey (key); Logger.debug ("Delete cached key:{}", CacheKey); Future<boolean> future = memcachedclient.delete (CacheKey); Try {future.get (3, Timeunit.seconds);} catch (Exception e) {future.cancel (false); Logger.error ("memcached Clear Cache exception, key={}, server={} ", cachekey,memcachedclient.getnodelocator (). Getprimary (CacheKey). Getsocketaddress (), e);}} @Overridepublic void clear () {try {memcachedclient.flush ();} catch (exception e) {logger.error ("Memcached performs flush exception", e);}} Protected object fromstorevalue (Object storevalue) {if (this.allownullvalues && storevalue instanceof nullholder) {return null;} Return storevalue;} Private static class nulLholder implements serializable {private static final long serialversionuid = -99681708140860560l;} Protected object tostorevalue (Object uservalue) {if (this.allownullvalues & & uservalue == null) {return null_holder;} Return uservalue;} Public void setname (String name) {this.name = name;} Public void setmemcachedclient (memcachedclient memcachedclient) {this.memcachedClient = memcachedclient;} Public void setexpiredduration (int expiredduration) {this.expiredDuration = Expiredduration;} Public void setallownullvalues (boolean allownullvalues) {this.allowNullValues = Allownullvalues;}}
This class implements the Cache API interface, overrides the save, remove, and remove methods, and does a null optimization. Therefore, the subsequent cache operation calls this custom method.
Iii. Custom Annotations
Customize @cacheable to Annotations @cacheablerelation@retention (retentionpolicy.runtime) @Target ({Elementtype.method}) @ cacheable (value = "R", key= "#distributId + ' _ ' + #supplierId") public @interface Cacheablerelation {}
Customize @cacheevict to Annotations @cacheevictrelation @Retention (retentionpolicy.runtime) @Target ({Elementtype.method}) @ Cacheevict (value = "R", key= "#relation. Distributor.id + ' _ ' + #relation. SupplierId") Public @interface Cacheevictrelation {}
Customize the @cacheput as a comment @cacheputrelation @Retention (retentionpolicy.runtime) @Target ({Elementtype.method}) @CachePut ( Value = "S", key= "#relation. Distributid + ' _ ' + #relation. SupplierId") public @interface Cacheputrelation {}
The use of annotations such as @cacheable, @CacheEvict, @CachePut, etc. is not covered here. The focus is on value and key, and you will find that this value appears in the config file, and then it has a valid time set! And the key setting can refer to Spel usage, of course, the attributes of its comments and condition and other conditions to judge, space is limited, please consult yourself.
Iv. Reference Articles
Open the Big God Blog article:Spring Cache abstract detailed
IBM Developerworks: Comment-driven Spring Cache cache Introduction
This article is from the "Learning and Thinking" blog, please be sure to keep this source http://linhongyu.blog.51cto.com/6373370/1677336
Spring MVC Integration memcached use of annotation-based practices