.net core 使用 AspectCore 实现简易的AopCache。
(第一次写博客,好紧张!!!)
源码地址:传送门
项目中有很多缓存的需求,能自己定义缓存key和时间,能根据key去清理缓存。
网上找了一圈,有很多基于aop的缓存组件,但是都不满足我的需求。故造了个轮子。
新建web项目 .net core mvc TestAopCache
安装 AopCache
Install-Package AopCache -Version 0.1.1
属性说明
AopCache一共3个属性:
Key:缓存的键值,字符串,可以包含占位符 如 {userId}。如果key为空,将用类名+方法名作为键值
Type:表示时间类型,枚举。秒、分、小时、天 四种。默认秒
Length:时间长度,0 表示永不过去。默认 0
标记方式有两种
1、在接口的方法上加 [AopCache]
2、没有接口,直接在类的方法上加 [AopCache],前提是此方法必须用 virtual修饰
存储方式
默认是 MemoryCache,不过你可以实现 IAopCacheProvider 接口,实现自己的存储。
新建 ITestService,在方法上加 [AopCache]
public interface ITestService { //默认时间单位是秒,长度为0,即永不过期 [AopCache(Key = "aaa")] string GetByKey(); //设置3秒过期 这里的“{userId}”,占位符。用参数 userId 的值去替换 [AopCache(Key = "bbb_{userId}", Length = 3)] string GetByKeyAndParamter(int userId); //设置十分钟过期 这里的“{req:Id}”,占位符。用参数 req里面的Id 的值去替换 [AopCache(Key = "ccc_{req:Id}_{type}", Type = CacheTimeType.Minute, Length = 10)] Task<UserInfo> GetUserInfo(int type, Req req); }
//实现接口
public class TestService : ITestService { public string GetByKey() { return Guid.NewGuid().ToString("N"); } public string GetByKeyAndParamter(int userId) { return Guid.NewGuid().ToString("N") + "---" + userId; } public async Task<UserInfo> GetUserInfo(int type, Req req) { return new UserInfo() { Id = new Random().Next(1, 100), Name = Guid.NewGuid().ToString("N") }; } }
直接在类的方法上加标签
public class TestSingleClass { [AopCache(Key = "TestSingleClassKey")] public virtual string Get() { return Guid.NewGuid().ToString("N"); } }
Startup中配置注入
public IServiceProvider ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { //... //注入打了标签的Service services.AddTransient<ITestService, TestService>(); services.AddTransient<TestSingleClass>(); //自定义存储 这里xxx表示 IAopCacheProvider 的实现 //services.AddAopCache<xxx>(); //默认内存存储 //返回IServiceProvider,由 AspectCore接管 return services.AddAopCacheUseDefaultMemoryProvider(); //此方法的内部实现,这里包装一层 //if (setupAction == null) //{ // services.AddMemoryCache(); //} //else //{ // services.AddMemoryCache(setupAction); //} //services.AddSingleton<IAopCacheProvider, DefaultAopCacheProvider>(); //services.ConfigureDynamicProxy(); //return services.BuildAspectInjectorProvider(); }
直接在HomeController 中使用
public class HomeController : Controller { private ITestService TestService { get; set; } private TestSingleClass TestSingleClass { get; set; } private IAopCacheProvider AopCacheProvider { get; set; } public HomeController(ITestService testService, TestSingleClass testSingleClass, IAopCacheProvider aopCacheProvider) { TestService = testService; TestSingleClass = testSingleClass; AopCacheProvider = aopCacheProvider; } public IActionResult Index() { //在这里清除某个key //清除 GetUserInfo AopCacheProvider.Remove("ccc_1000_1"); return View(); } public async Task<IActionResult> Privacy() { //第一次获取值 生成的key是 aaa var v1 = TestService.GetByKey(); //生成的key是 bbb_1,占位符被替换:bbb_{userId} => bbb_1 var v2 = TestService.GetByKeyAndParamter(1); //生成的key是 ccc_1000_1,占位符被替换:ccc_{req:Id}_{type} => ccc_1000_1 var v3 = await TestService.GetUserInfo(1, new Req() { Id = 1000 }); //直接在类的方法上加标记,但是方法必须加 virtual //生成的key是 TestSingleClassKey var v4 = TestSingleClass.Get(); //第二次获取值 var v1New = TestService.GetByKey(); var v2New = TestService.GetByKeyAndParamter(1); var v3New = await TestService.GetUserInfo(1, new Req() { Id = 1000 }); var v4New = TestSingleClass.Get(); var sb = new StringBuilder(); sb.AppendLine($"GetByKey(永不过期):第一次=> {v1}"); sb.AppendLine($"GetByKey(永不过期):第二次=> {v1New}"); sb.AppendLine($"GetByKeyAndParamter(3秒):第一次=> {v2}"); sb.AppendLine($"GetByKeyAndParamter(3秒):第二次=> {v2New}"); sb.AppendLine($"GetUserInfo(十分钟):第一次=> {Newtonsoft.Json.JsonConvert.SerializeObject(v3)}"); sb.AppendLine($"GetUserInfo(十分钟):第二次=> {Newtonsoft.Json.JsonConvert.SerializeObject(v3New)}"); sb.AppendLine($"TestSingleClass.Get(永不过期):第一次=> {v4}"); sb.AppendLine($"TestSingleClass.Get(永不过期):第二次=> {v4New}"); return Content(sb.ToString()); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } }
F5运行
点击 “Privacy”,疯狂刷新,查看效果。
切换回首页,清除 GetUserInfo 的缓存,再切换到Privacy,发现 GetUserInfo 的缓存已改变。
到此结束,如果你刚好有这需求,可以参考此文章。源码传到gayhub,求轻拍 ==