zoukankan      html  css  js  c++  java
  • .net core 使用 AspectCore 实现简易的AopCache。

    (第一次写博客,好紧张!!!)

    源码地址:传送门

    项目中有很多缓存的需求,能自己定义缓存key和时间,能根据key去清理缓存。

    网上找了一圈,有很多基于aop的缓存组件,但是都不满足我的需求。故造了个轮子。

    新建web项目 .net core mvc TestAopCache

    image

    安装 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运行

    image

    点击 “Privacy”,疯狂刷新,查看效果。

    image

    切换回首页,清除 GetUserInfo 的缓存,再切换到Privacy,发现 GetUserInfo 的缓存已改变。

    image

    到此结束,如果你刚好有这需求,可以参考此文章。源码传到gayhub,求轻拍 ==

  • 相关阅读:
    手把手带你玩转 DialogFragment
    紧张的去京东面试7,没想到可以成功拿下offer
    这个有点强,MySQL常用优化指南及大表优化思路(值得收藏)
    Java程序员两年经验斩获头条 Offer,技术杠杠的
    为什么大家都说 SELECT * 效率低
    Java程序员想要靠外包刷题,结果却大跌眼镜,心态都崩了
    一次请求在SpringMVC核心执行流程
    工作三年经验,一年内我靠这份javaBAT进阶面试题从13K到大厂25K
    用了这么久的数据库连接池,你知道原理吗?
    poj 3295 Tautology(栈)
  • 原文地址:https://www.cnblogs.com/ad313/p/10642554.html
Copyright © 2011-2022 走看看