zoukankan      html  css  js  c++  java
  • MVC 框架中的缓存

         在程序中加入缓存的目的很多是为了提高程序的性能,提高数据的查找效率,在MVC框架中也引入了非常多的缓存,比如Controller的匹配查找,Controller,ControllerDescriptorCache...大部分的缓存设计都是采用了key-value的结构;

    ControllerTypeCache

         ControllerTypeCache类是对应用程序集中的Controller类型进行缓存,当请求进入MVC框架中,需要根据RouteData中ControllerName 以及命名空间来进行查找出正确的Controller类型。如果程序比较大时,Controller就要对程序中所有的dll中的类进行查找匹配,效率肯定非常低下;

         在MVC框架中对于Controller类的查找匹配引入了ControllerTypeCache类,在缓存类中存在Dictionary<string, ILookup<string, Type>>的缓存结构,在这个结构中key为去掉Controller后缀的Controller类型的Name,Value 值为ILookup<string, Type>结构,其中key值为命名空间名称,Value 为Controller的类型;而且这些key都是忽略大小写;

         

         public void EnsureInitialized(IBuildManager buildManager)
         {
             if (_cache == null)
             {
                lock (_lockObj)
                {
                    if (_cache == null)
                     {
                         List<Type> controllerTypes = TypeCacheUtil.GetFilteredTypesFromAssemblies(TypeCacheName, IsControllerType, buildManager);
                         var groupedByName = controllerTypes.GroupBy(
                                              t => t.Name.Substring(0, t.Name.Length - "Controller".Length), StringComparer.OrdinalIgnoreCase);
                            _cache = groupedByName.ToDictionary(
                                                   g => g.Key,
                                                   g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
                                                   StringComparer.OrdinalIgnoreCase);
                        }
                    }
                }
            }

             ControllerTypeCache类中EnsureInitialized方法就是构建缓存结构,GetFilteredTypesFromAssemblies方法时获取到应用程序集中所有的Control类型,在MVC框架中会在应用程序启动时加载所有的dll类中的Controller类型然后调用IBuildManager接口的方法CreateCachedFile方法将这些类型序列到磁盘文件中,下次请求到来时直接从磁盘文件中加载,文件名字为“MVC-ControllerTypeCache.xml”;_cache 缓存文件的地址是在HttpRuntime.CodegenDir+"//UserCache//MVC-ControllerTypeCache.xml";

    ReaderWriterCache<TKey, TValue>
            ReaderWriterCache是一个读写缓存抽象类,它的缓存结构也是key-value的形式,在MVC框架中ControllerDescriptorCache类,ActionMethodDispatcherCache类都继承了这个抽象类;在ControllerDescriptorCache类中key为Controller的Type类型,Value为ControllerDescriptor类; ActionMethodDispatcherCache类中key为action方法的MethodInfo,Value为ActionMethodDispatcher类;

          在ReaderWriterCache类中有个重要的读取或是设置缓存的FetchOrCreateItem的方法;

     private readonly ReaderWriterLockSlim _readerWriterLock = new ReaderWriterLockSlim();
     protected TValue FetchOrCreateItem<TArgument>(TKey key, Func<TArgument, TValue> creator, TArgument state)
     {
       // first, see if the item already exists in the cache
        _readerWriterLock.EnterReadLock();
        try
        {
          TValue existingEntry;
          if (_cache.TryGetValue(key, out existingEntry))
            {
               return existingEntry;
            }
         }
         finally
         {
              _readerWriterLock.ExitReadLock();
         }
    
         // insert the new item into the cache
         TValue newEntry = creator(state);
         _readerWriterLock.EnterWriteLock();
         try
         {
            TValue existingEntry;
            if (_cache.TryGetValue(key, out existingEntry))
            {
               // another thread already inserted an item, so use that one
               return existingEntry;
             }
             _cache[key] = newEntry;
              return newEntry;
          }
          finally
          {
             _readerWriterLock.ExitWriteLock();
          }
        }

          在FetchOrCreateItem方法中引入了ReaderWriterLockSlim类,这个类的目的是用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问,当根据key获取vlaue值时,读取缓存时根据EnterReadLock方法加入读锁,当读取完毕后,通过ExitReadLock方法释放读锁;如果缓存没有命中,则通过调用创建类型的委托创建value并写入到缓存中,在写入缓存的之前会再次从缓存中读取,如果没有则写入,防止并发造成的重复写入;

      

         protected override ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext)
         {
             // Frequently called, so ensure delegate is static
             Type controllerType = controllerContext.Controller.GetType();
             ControllerDescriptor controllerDescriptor = DescriptorCache.GetDescriptor(
                     controllerType: controllerType,
                     creator: ReflectedAsyncControllerDescriptor.DefaultDescriptorFactory,
                     state: controllerType);
                return controllerDescriptor;
          }

     ReflectedAttributeCache

          ReflectedAttributeCache类时缓存作用于action方法中的一些特性的列表缓存,从这个缓存中可以很快获取到对于的方法的一些特性信息,在这个缓存类的类结构也是采用的key-value的形式;

         

          private static readonly ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionMethodSelectorAttribute>> _actionMethodSelectorAttributeCache = new ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionMethodSelectorAttribute>>();
            private static readonly ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionNameSelectorAttribute>> _actionNameSelectorAttributeCache = new ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionNameSelectorAttribute>>();
            private static readonly ConcurrentDictionary<MethodInfo, ReadOnlyCollection<FilterAttribute>> _methodFilterAttributeCache = new ConcurrentDictionary<MethodInfo, ReadOnlyCollection<FilterAttribute>>();
    
            private static readonly ConcurrentDictionary<Type, ReadOnlyCollection<FilterAttribute>> _typeFilterAttributeCache = new ConcurrentDictionary<Type, ReadOnlyCollection<FilterAttribute>>();

      在ReflectedAttributeCache类中存在了4种缓存,缓存的格式都是ConcurrentDictionary类型,

        _actionMethodSelectorAttributeCache 缓存:key 为action方法的MethodInfo,value为继承了ActionMethodSelectorAttribute抽象类的一些子类(HttpPostAttribute,HttpGetAttribute)的只读集合;ActionMethodSelectorAttribute类的目的是筛选请求的方式;

        _actionNameSelectorAttributeCache 缓存:key 为action方法的MethodInfo,value为继承了ActionNameSelectorAttribute抽象类的一些子类(ActionNameAttribute)的只读集合;ActionMethodSelectorAttribute类的目的是筛选请求方法的名字;

         _methodFilterAttributeCache 缓存:key 为action方法的MethodInfo,value为继承了FilterAttribute抽象类的一些子类的只读集合;FilterAttribute类的目的是action的过滤器特性;

        _typeFilterAttributeCache 缓存:key 为Controller类的Type,value为继承了FilterAttribute抽象类的一些子类的只读集合;FilterAttribute类的目的是Controller的过滤器特性;

     在ReflectedAttributeCache类中获取特性集合都是通过GetAttributes方法

      private static ReadOnlyCollection<TAttribute> GetAttributes<TMemberInfo, TAttribute>(ConcurrentDictionary<TMemberInfo, ReadOnlyCollection<TAttribute>> lookup, TMemberInfo memberInfo)
                where TAttribute : Attribute
                where TMemberInfo : MemberInfo
      {
            // Frequently called, so use a static delegate
            // An inline delegate cannot be used because the C# compiler does not cache inline delegates that reference generic method arguments
            return lookup.GetOrAdd( memberInfo,
                                   CachedDelegates<TMemberInfo, TAttribute>.GetCustomAttributes);
       }
    
      private static class CachedDelegates<TMemberInfo, TAttribute>
                where TAttribute : Attribute
                where TMemberInfo : MemberInfo
      {
            internal static Func<TMemberInfo, ReadOnlyCollection<TAttribute>> GetCustomAttributes = (TMemberInfo memberInfo) =>
             {
                    return new ReadOnlyCollection<TAttribute>((TAttribute[])memberInfo.GetCustomAttributes(typeof(TAttribute), inherit: true));
             };
      }


     
  • 相关阅读:
    Python面试题目--汇总
    MySQL索引背后的数据结构及算法原理
    Python中的str与unicode处理方法
    消息队列 RabbitMQ
    python采用pika库使用rabbitmq总结,多篇笔记和示例
    SQL总结(一)基本查询
    【IT笔试面试题整理】判断一个树是否是另一个的子树
    【IT笔试面试题整理】有序数组生成最小高度二叉树
    【IT笔试面试题整理】给定二叉树,给每层生成一个链表
    【IT笔试面试题整理】位操作
  • 原文地址:https://www.cnblogs.com/h20064528/p/5051273.html
Copyright © 2011-2022 走看看