• Orchard源码分析(4.4):Orchard.Caching.CacheModule类


    概述
    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 TypedParametertypeof(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, FuncAcquireContext<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<TypeType 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>
     
    参考资料:
  • 相关阅读:
    cd /d %~dp0是什么意思啊?
    [转]修改SDI主窗口Title
    版本控制
    (原创)日志处理(修改)
    (转)VC中让CListBox带有复选框
    (转)专业的程序员需要具备的思考能力:写一个程序需要注意多少细节问题
    vue中vcharts的使用
    1. 持续集成 简单介绍
    os.urandom函数用来获取一个指定长度的随机bytes对象
    python 列表中嵌套列表或列表推导式 如果合并成一个list
  • 原文地址:https://www.cnblogs.com/lhxsoft/p/5322615.html
Copyright © 2020-2023  润新知