重学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);
}
这里IDomainExtensionCacheStrategy 里面其实就是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了。
结
因为很多人没有去了解这个框架,也不需要了解这个框架,所以就不会发布到首页中。
重学c#系列——缓存[盛派源码分析cache](九)的更多相关文章
- Java入门系列之集合LinkedList源码分析(九)
前言 上一节我们手写实现了单链表和双链表,本节我们来看看源码是如何实现的并且对比手动实现有哪些可优化的地方. LinkedList源码分析 通过上一节我们对双链表原理的讲解,同时我们对照如下图也可知道 ...
- 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- Volley源码解析(三) 有缓存机制的情况走缓存请求的源码分析
Volley源码解析(三) 有缓存机制的情况走缓存请求的源码分析 Volley之所以高效好用,一个在于请求重试策略,一个就在于请求结果缓存. 通过上一篇文章http://www.cnblogs.com ...
- Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析
原文:Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析 一.RedissonLock#lock 源码分析 1.根据锁key计算出 slot,一个slot对 ...
- Java入门系列之集合HashMap源码分析(十四)
前言 我们知道在Java 8中对于HashMap引入了红黑树从而提高操作性能,由于在上一节我们已经通过图解方式分析了红黑树原理,所以在接下来我们将更多精力投入到解析原理而不是算法本身,HashMap在 ...
- Java入门系列之集合ArrayList源码分析(七)
前言 上一节我们通过排队类实现了类似ArrayList基本功能,当然还有很多欠缺考虑,只是为了我们学习集合而准备来着,本节我们来看看ArrayList源码中对于常用操作方法是如何进行的,请往下看. A ...
- Flask系列10-- Flask请求上下文源码分析
总览 一.基础准备. 1. local类 对于一个类,实例化得到它的对象后,如果开启多个线程对它的属性进行操作,会发现数据时不安全的 import time from threading import ...
- SSO单点登录系列1:cas客户端源码分析cas-client-java-2.1.1.jar
落雨 cas 单点登录 希望能给以后来研究cas的兄弟留下一点思路,也算是研究了两天的成果,外国人的代码写的很晦涩,翻译下来也没有时间继续跟进,所以有错误的还请大家跟帖和我讨论,qq 39426378 ...
- Java入门系列之集合Hashtable源码分析(十一)
前言 上一节我们实现了散列算法并对冲突解决我们使用了开放地址法和链地址法两种方式,本节我们来详细分析源码,看看源码中对于冲突是使用的哪一种方式以及对比我们所实现的,有哪些可以进行改造的地方. Hash ...
- 源码分析系列1:HashMap源码分析(基于JDK1.8)
1.HashMap的底层实现图示 如上图所示: HashMap底层是由 数组+(链表)+(红黑树) 组成,每个存储在HashMap中的键值对都存放在一个Node节点之中,其中包含了Key-Value ...
随机推荐
- C++ //类模板与继承 //类模板与继承 //注意: //1.当子类继承父类是一个类模板时,子类在声名的时候,要指定出父类中T的类型 //2.如果不指定,编译器无法给子类分配内存 //3.如果想灵活指定出父类中的T的类型,子类也需要变为类模板
1 #include <iostream> 2 #include <string> 3 #include<fstream> 4 using namespace st ...
- kafka的数据同步原理ISR、ACK、LEO、HW
1.数据可靠性保证,数据同步 为保证 producer 发送的数据,能可靠的发送到指定的 topic,topic 的每个 partition 收到 producer 发送的数据后,都需要向 produ ...
- 玩转SpringBoot:SpringBoot的几种定时任务实现方式
引言 在现代软件开发中,定时任务是一种常见的需求,用于执行周期性的任务或在特定的时间点执行任务.这些任务可能涉及数据同步.数据备份.报表生成.缓存刷新等方面,对系统的稳定性和可靠性有着重要的影响.Sp ...
- DDD笔记
笔记来源于b站视频 1.系统"老化" 需求难:程序员和产品经理沟通困难,更改需求难 开发难:对于上前行代码的类,更改很难,只能用if-else 创新难:对于之前老的技术笔试SSH想 ...
- ChCore—实验 3:进程与线程、异常处理 部分记录
思考题 1: 内核从完成必要的初始化到用户态程序的过程是怎么样的?尝试描述一下调用关系. 内核启动到用户程序启动的流程: main ├── uart_init ├── mm_init ├── arch ...
- [VueJsDev] 基础知识 - ES6循环使用手册
[VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html ES6循环使用手册 ::: details 目录 目录 ES ...
- 记录--【vue3】写hook三天,治好了我的组件封装强迫症。
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 我以前很喜欢封装组件,什么东西不喜欢别人的,总喜欢自己搞搞,这让人很有成就感,虽然是重复造轮子,但是能从无聊的crud业务中暂时解脱 ...
- vscode中vue代码提示插件
由来 基于(Vue 3 Snippets,Vue VSCode Snippets)插件集成而来,因为这俩插件目前没有集成最新vue代码片段,且集成内容相对较少,于是这个插件就诞生了 插件提示跟vue写 ...
- 深入在线文档系统的 MarkDown/Word/PDF 导出能力设计
深入在线文档系统的 MarkDown/Word/PDF 导出能力设计 当我们实现在线文档的系统时,通常需要考虑到文档的导出能力,特别是对于私有化部署的复杂ToB产品来说,文档的私有化版本交付能力就显得 ...
- 感悟:FPGA的串行及并行设计思路
前言 FPGA设计过程中, 会遇到大量的串行转并行或者并行转串行的问题; 这些问题主要体现在FPGA对于速度和面积的均衡上; 一般而言, FPGA使用并行的设计可以提高处理的速度, 消耗更多的资源; ...