ABP 源码解析 六. 缓存
2018-08-26 本文已影响22人
诸葛_小亮
介绍
此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。
通过解读ABP源码,可以提升ABP使用方式,可以提升编码意识,提高面向对象编程思想。
本篇文章主要介绍ABP框架的缓存实现机制。
UML
![](https://img.haomeiwen.com/i1397128/120e0576c94a9ec1.png)
- ICache:定义一个可以存储并通过键获取项目的缓存
- CacheBase:基类缓存,简单实现
ICache
- AbpMemoryCache:使用
MemoryCache
实现ICache
- ICacheManager:缓存管理器应该,单例对象,跟踪和管理缓存对象
- CacheManagerBase:缓存管理器的基类
- AbpMemoryCacheManager:使用
MemoryCache
实现ICacheManager
- ICacheConfigurator:缓存配置器
- CacheConfigurator:实现
ICacheConfigurator
- ICachingConfiguration:缓存系统配置
- CachingConfiguration:实现
ICachingConfiguration
源码解析
ICache
ICache主要是定义一个缓存项目接口,并且提供超时时间、获取值、设置缓存等内容。
ABP系统默认系统了四个项目:应用程式设置缓存、租户设置缓存、用户设置缓存、多语言脚本缓存
/// <summary>
/// Defines a cache that can be store and get items by keys.
/// 定义一个可以存储并通过键获取项目的缓存
/// </summary>
public interface ICache : IDisposable
{
/// <summary>
/// Unique name of the cache.
/// 缓存唯一的名称
/// </summary>
string Name { get; }
/// <summary>
/// Default sliding expire time of cache items.
/// Default value: 60 minutes (1 hour).
/// Can be changed by configuration.
/// 默认缓存过期时间
/// 默认值是1小时
/// 可以通过配置改变
/// </summary>
TimeSpan DefaultSlidingExpireTime { get; set; }
/// <summary>
/// Default absolute expire time of cache items.
/// Default value: null (not used).
/// 默认的缓存项的绝对过期时间
/// 默认值:null(没有使用)
/// </summary>
TimeSpan? DefaultAbsoluteExpireTime { get; set; }
/// <summary>
/// Gets an item from the cache.
/// This method hides cache provider failures (and logs them),
/// uses the factory method to get the object if cache provider fails.
/// 从缓存中获取一个项目
/// 这个方法隐藏了缓存提供者失败信息(并记录它们),如果缓存提供者失败,则使用工厂方法来获取对象
/// </summary>
/// <param name="key">Key</param>
/// <param name="factory">Factory method to create cache item if not exists
/// 如果不存在的话,创建缓存项的工厂方法
/// </param>
/// <returns>Cached item</returns>
object Get(string key, Func<string, object> factory);
/// <summary>
/// Gets an item from the cache.
/// This method hides cache provider failures (and logs them),
/// uses the factory method to get the object if cache provider fails.
/// </summary>
/// <param name="key">Key</param>
/// <param name="factory">Factory method to create cache item if not exists</param>
/// <returns>Cached item</returns>
Task<object> GetAsync(string key, Func<string, Task<object>> factory);
/// <summary>
/// Gets an item from the cache or null if not found.
/// 从缓存中获取一个项目,如果没有找到,则可以获得null
/// </summary>
/// <param name="key">Key</param>
/// <returns>Cached item or null if not found</returns>
object GetOrDefault(string key);
/// <summary>
/// Gets an item from the cache or null if not found.
/// </summary>
/// <param name="key">Key</param>
/// <returns>Cached item or null if not found</returns>
Task<object> GetOrDefaultAsync(string key);
/// <summary>
/// Saves/Overrides an item in the cache by a key.
/// Use one of the expire times at most (<paramref name="slidingExpireTime"/> or <paramref name="absoluteExpireTime"/>).
/// If none of them is specified, then
/// <see cref="DefaultAbsoluteExpireTime"/> will be used if it's not null. Othewise, <see cref="DefaultSlidingExpireTime"/>
/// will be used.
/// 在缓存中通过一个键来覆盖一个条目
/// </summary>
/// <param name="key">Key</param>
/// <param name="value">Value</param>
/// <param name="slidingExpireTime">Sliding expire time</param>
/// <param name="absoluteExpireTime">Absolute expire time</param>
void Set(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null);
/// <summary>
/// Saves/Overrides an item in the cache by a key.
/// Use one of the expire times at most (<paramref name="slidingExpireTime"/> or <paramref name="absoluteExpireTime"/>).
/// If none of them is specified, then
/// <see cref="DefaultAbsoluteExpireTime"/> will be used if it's not null. Othewise, <see cref="DefaultSlidingExpireTime"/>
/// will be used.
/// </summary>
/// <param name="key">Key</param>
/// <param name="value">Value</param>
/// <param name="slidingExpireTime">Sliding expire time</param>
/// <param name="absoluteExpireTime">Absolute expire time</param>
Task SetAsync(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null);
/// <summary>
/// Removes a cache item by it's key.
/// 通过它的键删除缓存项
/// </summary>
/// <param name="key">Key</param>
void Remove(string key);
/// <summary>
/// Removes a cache item by it's key (does nothing if given key does not exists in the cache).
/// </summary>
/// <param name="key">Key</param>
Task RemoveAsync(string key);
/// <summary>
/// Clears all items in this cache.
/// 清除缓存中的所有项
/// </summary>
void Clear();
/// <summary>
/// Clears all items in this cache.
/// </summary>
Task ClearAsync();
}
CacheBase
缓存项目基类只要实现了基本的存取操作,但是具体的实现,下沉到子类实现
/// <summary>
/// Base class for caches.
/// It's used to simplify implementing <see cref="ICache"/>.
/// 基类缓存
/// 简单实现<see cref="ICache"/>
/// </summary>
public abstract class CacheBase : ICache
{
public ILogger Logger { get; set; }
public string Name { get; }
public TimeSpan DefaultSlidingExpireTime { get; set; }
public TimeSpan? DefaultAbsoluteExpireTime { get; set; }
protected readonly object SyncObj = new object();
private readonly AsyncLock _asyncLock = new AsyncLock();
/// <summary>
/// Constructor.
/// </summary>
/// <param name="name"></param>
protected CacheBase(string name)
{
Name = name;
DefaultSlidingExpireTime = TimeSpan.FromHours(1);
Logger = NullLogger.Instance;
}
public virtual object Get(string key, Func<string, object> factory)
{
object item = null;
try
{
item = GetOrDefault(key);
}
catch (Exception ex)
{
Logger.Error(ex.ToString(), ex);
}
if (item == null)
{
lock (SyncObj)
{
try
{
item = GetOrDefault(key);
}
catch (Exception ex)
{
Logger.Error(ex.ToString(), ex);
}
if (item == null)
{
item = factory(key);
if (item == null)
{
return null;
}
try
{
Set(key, item);
}
catch (Exception ex)
{
Logger.Error(ex.ToString(), ex);
}
}
}
}
return item;
}
public virtual async Task<object> GetAsync(string key, Func<string, Task<object>> factory)
{
object item = null;
try
{
item = await GetOrDefaultAsync(key);
}
catch (Exception ex)
{
Logger.Error(ex.ToString(), ex);
}
if (item == null)
{
using (await _asyncLock.LockAsync())
{
try
{
item = await GetOrDefaultAsync(key);
}
catch (Exception ex)
{
Logger.Error(ex.ToString(), ex);
}
if (item == null)
{
item = await factory(key);
if (item == null)
{
return null;
}
try
{
await SetAsync(key, item);
}
catch (Exception ex)
{
Logger.Error(ex.ToString(), ex);
}
}
}
}
return item;
}
public abstract object GetOrDefault(string key);
public virtual Task<object> GetOrDefaultAsync(string key)
{
return Task.FromResult(GetOrDefault(key));
}
public abstract void Set(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null);
public virtual Task SetAsync(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null)
{
Set(key, value, slidingExpireTime);
return Task.FromResult(0);
}
public abstract void Remove(string key);
public virtual Task RemoveAsync(string key)
{
Remove(key);
return Task.FromResult(0);
}
public abstract void Clear();
public virtual Task ClearAsync()
{
Clear();
return Task.FromResult(0);
}
public virtual void Dispose()
{
}
}
AbpMemoryCache
AbpMemoryCache
是基于MemoryCache
实现 ICache
,使用具体的缓存技术实现缓存项目
/// <summary>
/// Implements <see cref="ICache"/> to work with <see cref="MemoryCache"/>.
/// 使用<see cref="MemoryCache"/> 实现 <see cref="ICache"/>
/// </summary>
public class AbpMemoryCache : CacheBase
{
private MemoryCache _memoryCache;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="name">Unique name of the cache</param>
public AbpMemoryCache(string name)
: base(name)
{
_memoryCache = new MemoryCache(new OptionsWrapper<MemoryCacheOptions>(new MemoryCacheOptions()));
}
public override object GetOrDefault(string key)
{
return _memoryCache.Get(key);
}
public override void Set(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null)
{
if (value == null)
{
throw new AbpException("Can not insert null values to the cache!");
}
if (absoluteExpireTime != null)
{
_memoryCache.Set(key, value, DateTimeOffset.Now.Add(absoluteExpireTime.Value));
}
else if (slidingExpireTime != null)
{
_memoryCache.Set(key, value, slidingExpireTime.Value);
}
else if (DefaultAbsoluteExpireTime != null)
{
_memoryCache.Set(key, value, DateTimeOffset.Now.Add(DefaultAbsoluteExpireTime.Value));
}
else
{
_memoryCache.Set(key, value, DefaultSlidingExpireTime);
}
}
public override void Remove(string key)
{
_memoryCache.Remove(key);
}
public override void Clear()
{
_memoryCache.Dispose();
_memoryCache = new MemoryCache(new OptionsWrapper<MemoryCacheOptions>(new MemoryCacheOptions()));
}
public override void Dispose()
{
_memoryCache.Dispose();
base.Dispose();
}
}
ICacheManager
缓存管理器应该,单例对象,跟踪和管理缓存对象
/// <summary>
/// An upper level container for <see cref="ICache"/> objects.
/// A cache manager should work as Singleton and track and manage <see cref="ICache"/> objects.
/// 缓存管理器应该,单例对象,跟踪和管理缓存对象
/// </summary>
public interface ICacheManager : IDisposable
{
/// <summary>
/// Gets all caches.
/// 获取所有缓存
/// </summary>
/// <returns>List of caches</returns>
IReadOnlyList<ICache> GetAllCaches();
/// <summary>
/// Gets a <see cref="ICache"/> instance.
/// It may create the cache if it does not already exists.
/// 获取缓存实例
/// 如果缓存不存在,则创建缓存
/// </summary>
/// <param name="name">
/// Unique and case sensitive name of the cache.
/// 缓存的唯一的名称,大小写敏感
/// </param>
/// <returns>The cache reference</returns>
[NotNull] ICache GetCache([NotNull] string name);
}
CacheManagerBase
缓存管理器的基类,实现基本的操作,将具体的算法下层到子类实现
/// <summary>
/// Base class for cache managers.
/// 缓存管理器的基类
/// </summary>
public abstract class CacheManagerBase : ICacheManager, ISingletonDependency
{
protected readonly IIocManager IocManager;
protected readonly ICachingConfiguration Configuration;
protected readonly ConcurrentDictionary<string, ICache> Caches;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="iocManager"></param>
/// <param name="configuration"></param>
protected CacheManagerBase(IIocManager iocManager, ICachingConfiguration configuration)
{
IocManager = iocManager;
Configuration = configuration;
Caches = new ConcurrentDictionary<string, ICache>();
}
public IReadOnlyList<ICache> GetAllCaches()
{
return Caches.Values.ToImmutableList();
}
public virtual ICache GetCache(string name)
{
Check.NotNull(name, nameof(name));
return Caches.GetOrAdd(name, (cacheName) =>
{
var cache = CreateCacheImplementation(cacheName);
var configurators = Configuration.Configurators.Where(c => c.CacheName == null || c.CacheName == cacheName);
foreach (var configurator in configurators)
{
configurator.InitAction?.Invoke(cache);
}
return cache;
});
}
public virtual void Dispose()
{
DisposeCaches();
Caches.Clear();
}
protected virtual void DisposeCaches()
{
foreach (var cache in Caches)
{
IocManager.Release(cache.Value);
}
}
/// <summary>
/// Used to create actual cache implementation.
/// 用于创建实际的缓存实现
/// </summary>
/// <param name="name">Name of the cache</param>
/// <returns>Cache object</returns>
protected abstract ICache CreateCacheImplementation(string name);
}
AbpMemoryCacheManager
使用MemoryCache
实现的ICacheManager
,使用具体的缓存组件实现ICacheManager,实现父类CacheManagerBase
的方法
/// <summary>
/// Implements <see cref="ICacheManager"/> to work with MemoryCache.
/// 使用MemoryCache实现<see cref="ICacheManager"/>
/// </summary>
public class AbpMemoryCacheManager : CacheManagerBase
{
public ILogger Logger { get; set; }
/// <summary>
/// Constructor.
/// </summary>
public AbpMemoryCacheManager(IIocManager iocManager, ICachingConfiguration configuration)
: base(iocManager, configuration)
{
Logger = NullLogger.Instance;
}
protected override ICache CreateCacheImplementation(string name)
{
return new AbpMemoryCache(name)
{
Logger = Logger
};
}
protected override void DisposeCaches()
{
foreach (var cache in Caches.Values)
{
cache.Dispose();
}
}
}
ICacheConfigurator
缓存配置器,配置单个缓存项目,主要是配置创建之后的调用方法
/// <summary>
/// A registered cache configurator.
/// 缓存配置器
/// </summary>
public interface ICacheConfigurator
{
/// <summary>
/// Name of the cache.
/// It will be null if this configurator configures all caches.
/// 缓存名称,如果这个配置器配置了所有的缓存,它就会是null
/// </summary>
string CacheName { get; }
/// <summary>
/// Configuration action. Called just after the cache is created.
/// 配置操作。在缓存创建之后调用
/// </summary>
Action<ICache> InitAction { get; }
}
ICachingConfiguration
缓存系统配置,配置多个ICache信息
/// <summary>
/// Used to configure caching system.
/// 缓存系统配置
/// </summary>
public interface ICachingConfiguration
{
/// <summary>
/// Gets the ABP configuration object.
/// ABP配置值系统
/// </summary>
IAbpStartupConfiguration AbpConfiguration { get; }
/// <summary>
/// List of all registered configurators.
/// 所有已注册的配置器列表
/// </summary>
IReadOnlyList<ICacheConfigurator> Configurators { get; }
/// <summary>
/// Used to configure all caches.
/// 用于配置所有缓存
/// </summary>
/// <param name="initAction">
/// An action to configure caches
/// This action is called for each cache just after created.
/// 配置缓存的操作
/// 这个动作在创建后的每个缓存中都被调用
/// </param>
void ConfigureAll(Action<ICache> initAction);
/// <summary>
/// Used to configure a specific cache.
/// 用于配置特定的缓存
/// </summary>
/// <param name="cacheName">Cache name</param>
/// <param name="initAction">
/// An action to configure the cache.
/// This action is called just after the cache is created.
/// </param>
void Configure(string cacheName, Action<ICache> initAction);
}
设计模式
- 模板方法模式:
ICacheManager
,CacheManagerBase
,AbpMemoryCacheManager
,父类实现主要算法,定义调用顺序和过程,子类实现具体算法 - 桥接模式:
ICacheManager
,ICache
独立变化Manager和Cache,是的Manager和Cache可以独自扩展
![](https://img.haomeiwen.com/i1397128/9a9b8a692b08f2be.jpg)