首页 > 技术文章 > 通过spring.net中的spring.caching CacheResult实现memcached缓存

dfg727 2013-08-08 10:55 原文

通过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 }

 

 

 

 

 

推荐阅读