概述
CacheModule也是一个Autofac模块。
 
一、CacheModule类
CacheModule将DefaultCacheManager注册为ICacheManager:
     public class CacheModule : Module {
         protected override void Load( ContainerBuilder builder) {
            builder.RegisterType<DefaultCacheManager>()
                .As< ICacheManager>()
                .InstancePerDependency();
        }
        //...
    }
如果类有一个接受ICacheManager型的参数的构造函数,Autofac容器在解析(Resolve)该类生成对象之前,会先解析一个ICacheManager型对象作为参数:
     public class CacheModule : Module {
        //...
        protected override void AttachToComponentRegistration(Autofac.Core. IComponentRegistry componentRegistry, Autofac.Core.IComponentRegistration registration) {
            var needsCacheManager = registration.Activator.LimitType
                .GetConstructors()
                .Any(x => x.GetParameters()
                .Any(xx => xx.ParameterType == typeof(ICacheManager )));
          
            if (needsCacheManager) {
                registration.Preparing += (sender, e) => {
                    var parameter = new TypedParameter(
                        typeof(ICacheManager ),
                        e.Context.Resolve< ICacheManager>(new TypedParameter( typeof(Type ), registration.Activator.LimitType)));
                    e.Parameters = e.Parameters.Concat( new[] { parameter });
                };
            }
        }
    }
Cache Manager是与类型相关的,这实际上是CacheModule存在的意义所在。比如Orchard.Environment.DefaultOrchardHost和其他类型不会共享同一个DefaultCacheManager对象。
 
二、DefaultCacheManager:ICacheManager类
DefaultCacheManager类公开了两个方法:
        public ICache <TKey, TResult> GetCache<TKey, TResult>() {
            return _cacheHolder.GetCache<TKey, TResult>(_component);
        }
 
        public TResult Get<TKey, TResult>(TKey key, Func< AcquireContext<TKey>, TResult> acquire) {
            return GetCache<TKey, TResult>().Get(key, acquire);
        }
第 一个方法可以获取类型相关的ICache<TKey,TResult>(Cache<TKey,TResult>)对象集合;第 二个方法通过Key值获取具体的某一个Cache Result,即实际的缓存值。Cache<TKey,TResult>会在下面介绍。
不难看出,DefaultCacheManager是对ICacheHolder的简单封装,就算没有DefaultCacheManager类,也可以不怎么方便地使用缓存机制,因为实际的缓存存取是交给ICacheHolder来处理的,默认使用的是DefaultCacheHolder,这是一个应用程序域级的单例。
 
三、DefaultCacheHolder:ICacheHolder类
绝大多数的缓存机制都是采用字典的形式,DefaultCacheHolder中使用线程安全的ConcurrentDictionary<CacheKey, object>型字典来保存缓存,这里称为类型缓存字典,注意该字典中并不存储实际的缓存值。为了方便,在这里我们把CacheKey称为类型缓存字典Key;object称为类型缓存字典Value, 实际类型为泛型Cache<TKey,TResult>:ICache<TKey,TResult>的封闭类型。 Cache<TKey,Result>内部也有一个字典,类型为ConcurrentDictionary<TKey,  CacheEntry>。在这里,TKey称为缓存字典Key,CacheEntry称为缓存字典Value
CacheEntry有一个类型为TResult名为Result的属性,这里称为缓存Result,这才是实际的缓存值。
 
在分析源码的时候要特别区分这些我们约定的概念:
1、类型缓存字典、类型缓存字典Key类型缓存字典Value
2、缓存字典、缓存字典Key、缓存字典Value和缓存Result。
 
在使用缓存时,我们是通过"缓存字典Key"来获取一个"缓存Result"。
 
DefaultCacheHolder仅公开了一个GetCache方法:
        public ICache<TKey, TResult> GetCache<TKey, TResult>(Type component) {
            var cacheKey = new CacheKey(component, typeof(TKey), typeof (TResult));
            var result = _caches.GetOrAdd(cacheKey, k => new Cache<TKey, TResult>(_cacheContextAccessor));
            return (Cache <TKey, TResult>)result;
        }
方法首先使用两个泛型参数的类型加上一个方法参数(Type型),可以构成一个CacheKey。CacheKey是一个三元组:
        class CacheKey : Tuple<Type, Type , Type> {
            public CacheKey(Type component, Type key, Type result)
                : base(component, key, result) {
            }
        }
然后从类型缓存字典中获取一个Cache<TKey, TResult>:ICache<TKey,TResult>对象。这时可以认为获取了一个类型相关的缓存字典。调用Cache<TKey, TResult>对象Get方法获取实际的缓存值。
 

DefaultCacheHolder 采用延迟缓存机制,在第一次从缓存中获取对象时才会去构建对象;提供可扩展的缓存到期、更新策略,比如使用Orchard.Services.Clock 类配合可以让缓存在某个具体的时间到期或一定时间间隔到期。缓存过期并不表示它在内存中被立即销毁,而是会在下一次尝试获取缓存的时候重新生成缓存。

 
 
相关类型(皆在Orchard.Caching命名空间下):
DefaultCacheManager : ICacheManager
DefaultCacheHolder : ICacheHolder
DefaultCacheContextAccessor : ICacheContextAccessor
DefaultParallelCacheContext : IParallelCacheContext
DefaultAsyncTokenProvider : IAsyncTokenProvider
AcquireContext<TKey>:IAcquireContext
SimpleAcquireContext : IAcquireContext
Signals : ISignals : IVolatileProvider : ISingletonDependency
Signals.Token : IVolatileToken(Private nested class)
Cache<TKey, TResult> : ICache<TKey, TResult>

CacheEntry(Private class)

Weak<T>
 
参考资料:

Orchard源码分析(4.4):Orchard.Caching.CacheModule类的更多相关文章

  1. Orchard源码分析(5):Host相关(Orchard.Environment.DefaultOrchardHost类)

    概述 Host 是应用程序域级的单例,代表了Orchard应用程序.其处理应用程序生命周期中的初始化.BeginRequest事件.EndRequest事件等. 可以简单理解为HttpApplicat ...

  2. Spring源码分析——BeanFactory体系之抽象类、类分析(二)

    上一篇分析了BeanFactory体系的2个类,SimpleAliasRegistry和DefaultSingletonBeanRegistry——Spring源码分析——BeanFactory体系之 ...

  3. Orchard源码分析(1):Orchard架构

      本文主要参考官方文档"How Orchard works"以及Orchardch上的翻译.   源码分析应该做到庖丁解牛,而不是以管窥豹或瞎子摸象.所以先对Orchard架构有 ...

  4. Spring源码分析——BeanFactory体系之抽象类、类分析(一)

    上一篇介绍了BeanFactory体系的所有接口——Spring源码分析——BeanFactory体系之接口详细分析,本篇就接着介绍BeanFactory体系的抽象类和接口. 一.BeanFactor ...

  5. Thinkphp源码分析系列(二)–引导类

    在上一章我们说到,ThinkPHP.php在设置完框架所需要的变量和调教好环境后,在最后调用了  Think\Think::start();  即Think命名空间中的Think类的静态方法start ...

  6. spring源码分析系列 (5) spring BeanFactoryPostProcessor拓展类PropertyPlaceholderConfigurer、PropertySourcesPlaceholderConfigurer解析

    更多文章点击--spring源码分析系列 主要分析内容: 1.拓展类简述: 拓展类使用demo和自定义替换符号 2.继承图UML解析和源码分析 (源码基于spring 5.1.3.RELEASE分析) ...

  7. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第1节: FastThreadLocal的使用和创建

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 概述: FastThreadLocal我们在剖析堆外内存分配的时候简单介绍过, 它类似于JDK的ThreadL ...

  8. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第2节: FastThreadLocal的set方法

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第二节: FastThreadLocal的set方法 上一小节我们学习了FastThreadLocal的创建和 ...

  9. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第3节: recycler的使用和创建

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第三节: recycler的使用和创建   这一小节开始学习recycler相关的知识, recycler是n ...

  10. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第4节: recycler中获取对象

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第四节: recycler中获取对象 这一小节剖析如何从对象回收站中获取对象: 我们回顾上一小节demo的ma ...

随机推荐

  1. 由一段JS代码引发的思考

    不知道大家在编程的时候有没有遇到过这种情况,就是在循环遍历删除一部分内容的时候,发现只能删除其中一部分,而另一部分却总也删不掉,然后觉得自己的逻辑没有问题啊,于是陷入了深深的抑郁之中…… 昨天在处理一 ...

  2. OneThink学习笔记02----数据字典(即OneThink项目数据库里的表及其字段)

    action 字段 类型 注释 id int(11) unsigned 自增主键 name char(30) 行为唯一标识 title char(80) 行为说明 remark char(140) 行 ...

  3. 【C++实现python字符串函数库】二:字符串匹配函数startswith与endswith

    [C++实现python字符串函数库]字符串匹配函数startswith与endswith 这两个函数用于匹配字符串的开头或末尾,判断是否包含另一个字符串,它们返回bool值.startswith() ...

  4. Java多线程与并发库高级应用-同步集合

    ArrayBlockingQueue LinkedBlockingQueue 数组是连续的一片内存 链表是不连续的一片内存  传统方式下用Collections工具类提供的synchronizedCo ...

  5. 【BZOJ-2177】曼哈顿最小生成树 Kruskal + 树状数组

    2177: 曼哈顿最小生成树 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 190  Solved: 77[Submit][Status][Discu ...

  6. Invalid initial heap size: -Xms

    -Xxs512m注意 Xxs 和 512m中间无空格就行了.

  7. Linux Overflow Vulnerability General Hardened Defense Technology、Grsecurity/PaX

    Catalog . Linux attack vector . Grsecurity/PaX . Hardened toolchain . Default addition of the Stack ...

  8. 动态添加和更改F7编辑器(div和editGrid列)

    //更改列编辑器 waf("#editGrid").wafGrid("setColumnConfig", "settlementType", ...

  9. MATLAB for循环优化三例

    最近一周,对MATLAB有进行了新一轮的学习,对其矩阵化编程的思维有了更深入的了解.确实精妙! 例1: 将矩阵A= [1 2 3; 2 4 3; 3 4 5]中所有的数字3替换为33. 如果还停留在C ...

  10. maven 的 scope的含义

    依赖范围控制哪些依赖在哪些classpath 中可用,哪些依赖包含在一个应用中.让我们详细看一下每一种范围: compile (编译范围) compile是默认的范围:如果没有提供一个范围,那该依赖的 ...