通过spring.net中的spring.caching CacheResult实现memcached缓存
1.SpringMemcachedCache.cs
2.APP.config
3.Program.cs
4.Common
待解决问题:CacheResult,CacheResultItems有什么区别????
SpringMemcachedCache.cs memcached的实现, 继承了Spring.Caching.AbstractCache, memcached的实现用了Enyim.Caching
1 using System; 2 using Spring.Caching; 3 using System.Web; 4 using System.Collections; 5 using System.Web.Caching; 6 using Enyim.Caching; 7 using Enyim.Caching.Memcached; 8 9 namespace Demo.Common 10 { 11 /// <summary> 12 /// An <see cref="ICache"/> implementation backed by ASP.NET Cache (see <see cref="HttpRuntime.Cache"/>). 13 /// </summary> 14 /// <remarks> 15 /// <para> 16 /// Because ASP.NET Cache uses strings as cache keys, you need to ensure 17 /// that the key object type has properly implemented <b>ToString</b> method. 18 /// </para> 19 /// <para> 20 /// Despite the shared underlying <see cref="HttpRuntime.Cache"/>, it is possible to use more than 21 /// one instance of <see cref="AspNetCache"/> without interfering each other. 22 /// </para> 23 /// </remarks> 24 /// <author>Aleksandar Seovic</author> 25 /// <author>Erich Eichinger</author> 26 public class SpringMemcachedCache : AbstractCache 27 { 28 #region Fields 29 30 // logger instance for this class 31 private static MemcachedClient memcachedClient = null; 32 private static object initLock = new object(); 33 34 #endregion 35 36 private MemcachedClient MemcachedClient 37 { 38 get 39 { 40 if (memcachedClient == null) 41 { 42 lock (initLock) 43 { 44 if (memcachedClient == null) 45 { 46 memcachedClient = new MemcachedClient(); 47 } 48 } 49 } 50 51 return memcachedClient; 52 } 53 } 54 55 /// <summary> 56 /// Retrieves an item from the cache. 57 /// </summary> 58 /// <param name="key"> 59 /// Item key. 60 /// </param> 61 /// <returns> 62 /// Item for the specified <paramref name="key"/>, or <c>null</c>. 63 /// </returns> 64 public override object Get(object key) 65 { 66 object result = key == null ? null : MemcachedClient.Get(GenerateKey(key)); 67 return result; 68 } 69 70 /// <summary> 71 /// Removes an item from the cache. 72 /// </summary> 73 /// <param name="key"> 74 /// Item key. 75 /// </param> 76 public override void Remove(object key) 77 { 78 if (key != null) 79 { 80 MemcachedClient.Remove(GenerateKey(key)); 81 } 82 } 83 84 /// <summary> 85 /// Inserts an item into the cache. 86 /// </summary> 87 /// <param name="key"> 88 /// Item key. 89 /// </param> 90 /// <param name="value"> 91 /// Item value. 92 /// </param> 93 /// <param name="timeToLive"> 94 /// Item's time-to-live (TTL). 95 /// </param> 96 protected override void DoInsert(object key, object value, TimeSpan timeToLive) 97 { 98 MemcachedClient.Store(StoreMode.Set, GenerateKey(key), value, timeToLive); 99 } 100 101 /// <summary> 102 /// Generate a key to be used for the underlying <see cref="Cache"/> implementation. 103 /// </summary> 104 /// <param name="key"></param> 105 /// <returns></returns> 106 public string GenerateKey(object key) 107 { 108 return key.ToString(); 109 } 110 111 public override ICollection Keys 112 { 113 get { throw new NotSupportedException(); } 114 } 115 } 116 }
APP.config 配置enyim.com, memcache, spring.net
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <configSections> 4 <sectionGroup name="enyim.com"> 5 <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/> 6 <!-- log --> 7 <section name="log" type="Enyim.Caching.Configuration.LoggerSection, Enyim.Caching" /> 8 </sectionGroup> 9 10 <sectionGroup name="spring"> 11 <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> 12 <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> 13 </sectionGroup> 14 </configSections> 15 16 <enyim.com> 17 <memcached> 18 <servers> 19 <add address="127.0.0.1" port="11211"/> 20 </servers> 21 <socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00"/> 22 </memcached> 23 </enyim.com> 24 25 <spring> 26 <context> 27 <resource uri="config://spring/objects" /> 28 </context> 29 <objects xmlns="http://www.springframework.net" > 30 <object id="CacheAspect" type="Spring.Aspects.Cache.CacheAspect, Spring.Aop"/> 31 <object id="autoBOProxyCreator" type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop"> 32 <property name="ObjectNames"> 33 <list> 34 <value>*BO</value> 35 </list> 36 </property> 37 <property name="InterceptorNames"> 38 <list> 39 <value>CacheAspect</value> 40 </list> 41 </property> 42 </object> 43 44 <object id="cachedTestBO" type="Demo.App.CachedTestBO, Demo.App"></object> 45 46 <object id="MemCachedCache" type="Demo.Common.SpringMemcachedCache, Demo.Common"> 47 <property name="TimeToLive" value="00:05:00"/> 48 </object> 49 50 <object id="MemCachedCache-Short" type="Demo.Common.SpringMemcachedCache, Demo.Common"> 51 <property name="TimeToLive" value="00:05:00"/> 52 </object> 53 54 <object id="MemCachedCache-Long" type="Demo.Common.SpringMemcachedCache, Demo.Common"> 55 <property name="TimeToLive" value="00:30:00"/> 56 </object> 57 58 </objects> 59 </spring> 60 61 62 </configuration>
App Program.cs 测试效果
1.要从spring中进入的才会调用, 直接实例化进入不会调用
2.CacheName - "SpringCache" 对应spring配置中的id="SpringCache"节点,是实现cache的类
3.Key="'prefix.key.'+#cacheId" 传人cachedId=1对应生成以后的key为 prefix.key.1
复杂点的Key组合见下面
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using Demo.Common; using Spring.Caching; using Spring.Context; using Spring.Context.Support; namespace Demo.App { class Program { private static void Main(string[] args) { //通过spring.net来调用函数 IApplicationContext ctx = ContextRegistry.GetContext(); IDictionary testDictionary = ctx.GetObjectsOfType(typeof(ITestBO)); foreach (DictionaryEntry entry in testDictionary) { string name = (string)entry.Key; ITestBO service = (ITestBO)entry.Value; Console.WriteLine(name + " intercept: "); //第一次运行函数并保存到memcached Console.WriteLine("nowTime:" + DateTime.Now.ToString("T") + " testTime:" +service.TestMethod(1, new object[]{"one", "two"})); Console.WriteLine(); Thread.Sleep(5); //休眠5秒以便第二次调用查看是否有保存到memcached //第二次运行从memcached中读取数据 Console.WriteLine("nowTime:" + DateTime.Now.ToString("T") + " testTime:" + service.TestMethod(1, new object[] { "one", "two" })); Console.WriteLine(); } //手动实例化,不会从memcached中读取数据,因为没有运行到CacheResult中去 ITestBO test = new CachedTestBO(); test.TestMethod(2); Console.ReadLine(); } } public interface ITestBO { string TestMethod(int cacheId, params object[] elements); } public class CachedTestBO : ITestBO { //生成的key类似HK-MainSubAccountMap-1 [CacheResult(CacheName = SpringCache.NormalCache, Key = SpringCache.SpringCacheCountryPrefix +"+'" + SpringCacheKey.MainSubAccountMap + "'" + "+'-' + #cacheId")] public string TestMethod(int cacheId, params object[] elements) { return DateTime.Now.ToString("T"); } } }
Common类
1 namespace Demo.Common 2 { 3 public static class ApplicationVariables 4 { 5 private static string countryCode; 6 public static string CountryCode 7 { 8 get 9 { 10 if (countryCode == null) 11 { 12 countryCode = "HK"; 13 } 14 return countryCode; 15 } 16 } 17 } 18 19 public static class SpringCache 20 { 21 public const string SpringCacheCountryPrefix = @"T(Demo.Common.ApplicationVariables).CountryCode + '-'"; 22 public const string NormalCache = "MemCachedCache"; 23 24 public const string AspnetCache = "AspnetCache"; 25 } 26 27 public static class SpringCacheKey 28 { 29 public const string MainSubAccountMap = "MainSubAccountMap"; 30 31 public const string BOSetting = "BOSetting"; 32 } 33 }