通过spring.net中的spring.caching CacheResult实现memcached缓存
通过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)
{
returnDateTime.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 }
页:
[1]