重学c#系列——缓存[盛派源码分析cache](九)
前言
以前整理过缓存的东西在:
https://www.cnblogs.com/aoximin/p/12727659.html
只是粗略的例子,因为真的要去介绍缓存这个东西,要从内存开始,是一个有时间系列。
该文通过分析盛派源码,简单介绍如何实现一个简单的缓存机制。
正文
查看源码的出发点,我当时是这样想的,无论你采用哪种缓存,那么你都得暴露出一个object,让我可以进程增删改查吧。
在BaseContainer中,查看到:
/// <summary> /// 获取符合当前缓存策略配置的缓存的操作对象实例 /// </summary> protected static IBaseObjectCacheStrategy /*IBaseCacheStrategy<string,Dictionary<string, TBag>>*/ Cache { get { //使用工厂模式或者配置进行动态加载 //return CacheStrategyFactory.GetContainerCacheStrategyInstance(); //以下代码可以实现缓存“热切换”,损失的效率有限。如果需要追求极致效率,可以禁用type的判断 var containerCacheStrategy = ContainerCacheStrategyFactory.GetContainerCacheStrategyInstance()/*.ContainerCacheStrategy*/; if (_containerCache == null || _containerCache.GetType() != containerCacheStrategy.GetType()) { _containerCache = containerCacheStrategy; } if (_baseCache == null) { _baseCache = _baseCache ?? containerCacheStrategy.BaseCacheStrategy(); } return _baseCache; } }
像这种属性,不用看肯定是单例了。
ContainerCacheStrategyFactory 是一个生产者,那么看下它到底生成了啥吧。
GetContainerCacheStrategyInstance:
public static IContainerCacheStrategy GetContainerCacheStrategyInstance() { //从底层进行判断 var containerCacheStrategy = CacheStrategyFactory.GetExtensionCacheStrategyInstance(ContainerCacheStrategyDomain.Instance) as IContainerCacheStrategy; return containerCacheStrategy; }
ContainerCacheStrategyFactory 相当于是一片生产园container,CacheStrategyFactory是园区里面得工厂,建筑学。
好的,那么就看一下CacheStrategyFactory这个工程到底生产了啥吧。
查看:ContainerCacheStrategyDomain.Instance
public class ContainerCacheStrategyDomain : ICacheStrategyDomain { #region 单例 /// <summary> /// LocalCacheStrategy的构造函数 /// </summary> ContainerCacheStrategyDomain() : base() { } //静态LocalCacheStrategy public static ICacheStrategyDomain Instance { get { return Nested.instance;//返回Nested类中的静态成员instance } } class Nested { static Nested() { } //将instance设为一个初始化的LocalCacheStrategy新实例 internal static readonly ContainerCacheStrategyDomain instance = new ContainerCacheStrategyDomain(); } #endregion private const string IDENTITY_NAME= "6526BBC0-718A-4F47-9675-D6DF6E1CE125";//固定值,请勿修改 private const string DOMAIN_NAME = "WeixinContainer";//固定值,请勿修改。同时会作为缓存键命名空间的子级名称 public string IdentityName { get { return IDENTITY_NAME; } } public string DomainName { get { return DOMAIN_NAME; } } }
里面是一些固定值:
private const string IDENTITY_NAME= "6526BBC0-718A-4F47-9675-D6DF6E1CE125";//固定值,请勿修改 private const string DOMAIN_NAME = "WeixinContainer";//固定值,请勿修改。同时会作为缓存键命名空间的子级名称
看到这种情况,可以想象到基本是和注册有关(注册服务)。
然后进GetExtensionCacheStrategyInstance看下:
/// <summary> /// 获取指定领域缓存的换存策略 /// </summary> /// <param name="cacheStrategyDomain">领域缓存信息(需要为单例)CacheStrategyDomain</param> /// <returns></returns> public static IDomainExtensionCacheStrategy GetExtensionCacheStrategyInstance(ICacheStrategyDomain cacheStrategyDomain) { return CacheStrategyDomainWarehouse.GetDomainExtensionCacheStrategy(GetObjectCacheStrategyInstance(), cacheStrategyDomain); }
cacheStrategyDomain 是我们传进来得是一个实体类,后续猜测是一个注册标识对象。
GetObjectCacheStrategyInstance 看下这个干啥了。
/// <summary> /// 注册当前全局环境下的缓存策略,并立即启用。 /// </summary> /// <param name="func">如果为 null,将使用默认的本地缓存策略(LocalObjectCacheStrategy.Instance)</param> public static void RegisterObjectCacheStrategy(Func<IBaseObjectCacheStrategy> func) { ObjectCacheStrateFunc = func; if (func != null) { ObjectCacheStrategy = func(); } } /// <summary> /// 获取全局缓存策略 /// </summary> /// <returns></returns> public static IBaseObjectCacheStrategy GetObjectCacheStrategyInstance() { if (ObjectCacheStrateFunc == null) { return LocalObjectCacheStrategy.Instance; } return ObjectCacheStrateFunc(); }
上面RegisterObjectCacheStrategy表示我们可以注册一种缓存策略,ObjectCacheStrateFunc 将会保存。
GetObjectCacheStrategyInstance 就是我们需要看的,如果我们没有注册得话,那么他就会用本地的缓存,LocalObjectCacheStrategy.Instance。
查看LocalObjectCacheStrategy.Instance是什么?
里面是一堆方法,设置key value 过期时间等。不过我找到了这个:
static LocalObjectCacheHelper() { LocalObjectCache = HttpRuntime.Cache; }
默认使用的是:HttpRuntime.Cache;
好的,那么参数我们都知道了,那么看下return CacheStrategyDomainWarehouse.GetDomainExtensionCacheStrategy(GetObjectCacheStrategyInstance(), cacheStrategyDomain);中的GetDomainExtensionCacheStrategy干了啥吧。
/// <summary> /// 获取领域缓存(指定特定 的IBaseObjectCacheStrategy 缓存策略对象) /// </summary> /// <param name="baseObjectCacheStrategy">IBaseObjectCacheStrategy 缓存策略对象</param> /// <param name="cacheStrategyDomain">缓存领域</param> /// <returns></returns> public static IDomainExtensionCacheStrategy GetDomainExtensionCacheStrategy(IBaseObjectCacheStrategy baseObjectCacheStrategy, ICacheStrategyDomain cacheStrategyDomain) { CacheStrategyDomainMappingCollection mappingCollection = GetMappingCollection(cacheStrategyDomain.IdentityName); if (mappingCollection.ContainsKey(baseObjectCacheStrategy)) { return ((Dictionary<IBaseObjectCacheStrategy, CacheStrategyDomainMappingItem>)mappingCollection)[baseObjectCacheStrategy].DomainExtensionCacheStrategy; } UnregisteredDomainCacheStrategyException ex = new UnregisteredDomainCacheStrategyException(cacheStrategyDomain.GetType(), baseObjectCacheStrategy.GetType()); SenparcTrace.BaseExceptionLog(ex); throw ex; }
上面的从代码表面意思就是去一个映射集合中更具identityName查找,如果没有的话就抛出异常,如果有的话,就返回注册过的对象。
/// <summary> /// 获取某个领域内的所有CacheStrategyDomainMappingCollection /// </summary> /// <param name="identityName"></param> /// <returns></returns> private static CacheStrategyDomainMappingCollection GetMappingCollection(string identityName) { if (!_extensionCacheStrategyInstance.ContainsKey(identityName)) { _extensionCacheStrategyInstance[identityName] = new CacheStrategyDomainMappingCollection(); } return _extensionCacheStrategyInstance[identityName]; }
好吧,既然是这样那么肯定有注册啊。
找到注册:
/// <summary> /// 注册领域缓存 /// </summary> /// <param name="domainCacheStrategy"></param> public static void RegisterCacheStrategyDomain(IDomainExtensionCacheStrategy domainCacheStrategy) { string identityName = domainCacheStrategy.CacheStrategyDomain.IdentityName; IBaseObjectCacheStrategy key = domainCacheStrategy.BaseCacheStrategy(); CacheStrategyDomainMappingCollection mappingCollection = GetMappingCollection(identityName); CacheStrategyDomainMappingItem cacheStrategyDomainMappingItem2 = ((Dictionary<IBaseObjectCacheStrategy, CacheStrategyDomainMappingItem>)mappingCollection)[key] = new CacheStrategyDomainMappingItem(domainCacheStrategy); }
这里IDomainE ad8 xtensionCacheStrategy 里面其实就是IBaseObjectCacheStrategy baseObjectCacheStrategy, ICacheStrategyDomain cacheStrategyDomain。
public interface IDomainExtensionCacheStrategy { /// <summary> /// 领域缓存定义 /// </summary> ICacheStrategyDomain CacheStrategyDomain { get; } /// <summary> /// 使用的基础缓存策略 /// </summary> Func<IBaseObjectCacheStrategy> BaseCacheStrategy { get; } /// <summary> /// 向底层缓存注册当前缓存策略 /// </summary> /// <param name="extensionCacheStrategy">扩展缓存策略实例</param> void RegisterCacheStrategyDomain(IDomainExtensionCacheStrategy extensionCacheStrategy); }
其实后面就是一个ioc了。
结
因为很多人没有去了解这个框架,也不需要了解这个框架,所以就不会发布到首页中。
- Mybatis源码分析之Cache二级缓存原理 (五)
- android轻量级开源缓存框架——ASimpleCache(ACache)源码分析(封装好了一个工具类供大家使用)
- android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- 【Android开源项目分析】android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- jQuery源码分析-07数据缓存-Cache
- 【Android开源项目分析】android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- jQuery-1.9.1源码分析系列(四) 缓存系统
- android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- lucene4.5源码分析系列:索引缓存以及刷新
- jQuery-1.9.1源码分析系列(四) 缓存系统
- 缓存框架 ASimpleCache 源码分析地址收藏
- 【Android开源项目分析】android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- MyCat源码分析系列之——BufferPool与缓存机制
- android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- 【强烈推荐】开源C#工具类MSCL系列(四)缓存Cache帮助类
- android轻量级开源缓存框架——ASimpleCache(ACache)源码分析
- redis客户端Jedis源码分析系列——从缓存池中获取资源和销毁资源
- Android轻量级开源缓存框架——ASimpleCache(ACache)源码分析