首页 > 数据库 >AOP-Redis缓存

AOP-Redis缓存

时间:2023-07-28 17:33:59浏览次数:35  
标签:缓存 string Redis arg redis key AOP invocation

我没有单独使用过Redis,细节我可能解释不到位。该文章是采用依赖注入实现AOP-Redis缓存功能的 、

之前有写实现Memory缓存的。异曲同工之妙。

使用Redis离不开安装get包:StackExchange.Redis.

操作流程:

  1. 创建一个RedisAOP的.cs文件。继承IInterceptor的接口,允许程序进行拦截。该接口应该依赖于Autofac,所以依赖注入最好使用AUtofac。
  2. 实现接口的方法Intercept。拦截的功能的操作主要在此处执行。
  3. 老张的项目是有一个baseAop的,因为RedisAOP和MemoryAOP都是属于缓存,有公共的方法。例如截取Key值等。初学我就不搞太麻烦了。一个一个手写比较容易记住。
  4. 定义一个接口一个实现。IRedisCaching,RedisCaching。该实现主要是向Redis存储值和取值。所以定义两个方法,Get获取缓存,Set存入缓存。
  5. RedisCaching里依赖注入ConnectionMultiplexer、这个代表Redis的连接字符串对象(应该可以这么理解,也可能我说的不太准确)。通过该对象的GetDatabase()获取redis内的数据库链接对象。然后使用StringGet,或者StringSet来存储或读取缓存。
  6. 将接口注入到第一步的RedisAOP中,让我们可以进行操作Redis。
  7. 很重要的一部分。将IRedisCaching和RedisCaching注入程序,以至于我们可以依赖注入在RedisAOP中使用。其次!!!很重要的一部分不能忘记ConnectionMultiplexer也要注入进去!!!我一开始因为不常用redis。脑子抽抽忘记了。
  • RedisAOP代码
    public class RedisAOP : IInterceptor
        {
            protected readonly IRedisCaching redis; 
    
            public RedisAOP(IRedisCaching _redis)
            {
                this.redis = _redis;
            }
            public void Intercept(IInvocation invocation)
            {
                var method = invocation.MethodInvocationTarget ?? invocation.Method;
                //获取自定义缓存键
                var cacheKey = CustomCacheKey(invocation);
                //根据key获取相应的缓存值
                var cacheValue = redis.GetValue(cacheKey).Result;
                if (cacheValue != null)
                {
                    //动态返回类型
                    Type returnType;
                    //获取传入方法的返回类型。如果是多个就取默认第一个
                    if (typeof(Task).IsAssignableFrom(method.ReturnType))
                    {
                        returnType = method.ReturnType.GenericTypeArguments.FirstOrDefault();
                    }
                    else
                    {
                        returnType = method.ReturnType;
                    }
                    //将数据解析成方法返回类型
                    dynamic _result = JsonSerializer.Deserialize(cacheValue, returnType);
                    invocation.ReturnValue = (typeof(Task).IsAssignableFrom(method.ReturnType)) ? Task.FromResult(_result) : _result;
                    return;
                }
                //去执行当前的方法
                invocation.Proceed();
                //存入缓存
                if (!string.IsNullOrWhiteSpace(cacheKey))
                {
                    redis.Set(cacheKey, invocation.ReturnValue,TimeSpan.FromHours(24));
                }
            }
    
            /// <summary>
            /// object 转 string
            /// </summary>
            /// <param name="arg"></param>
            /// <returns></returns>
            protected static string GetArgumentValue(object arg)
            {
                if (arg is DateTime || arg is DateTime?)
                {
                    return ((DateTime)arg).ToString("yyyyMMddHHmmss");
                }
    
                if (arg is string || arg is ValueType || arg is Nullable)
                {
                    return arg.ToString();
                }
    
                if (arg != null)
                {
                    if (arg.GetType().IsClass)
                    {
                        return MD5Helper.MD5Encrypt16(JsonSerializer.Serialize(arg));
                    }
                }
    
                return string.Empty;
            }
    
            /// <summary>
            /// 自定义缓存的key
            /// </summary>
            /// <param name="invocation"></param>
            /// <returns></returns>
            protected string CustomCacheKey(IInvocation invocation)
            {
                var typeName = invocation.TargetType.Name;
                var methodName = invocation.Method.Name;
                var methodArguments = invocation.Arguments.Select(GetArgumentValue).Take(3).ToList();//获取参数列表,最多三个
    
                string key = $"{typeName}:{methodName}:";
                foreach (var param in methodArguments)
                {
                    key = $"{key}{param}:";
                }
                return key.TrimEnd(':');
            }
        }
    View Code
  • IRedisCaching/RedisCaching代码
    public class RedisCaching : IRedisCaching
        {
            private readonly ConnectionMultiplexer redis;
            private readonly IDatabase database;
            public RedisCaching(ConnectionMultiplexer _redis)
            {
                this.redis = _redis;
                database = _redis.GetDatabase();
            }
            /// <summary>
            /// 获取值
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public async Task<string> GetValue(string key)
            {
                return await database.StringGetAsync(key);
            }
            /// <summary>
            /// 存储值
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="cacheTime">过期时间</param>
            /// <returns></returns>
            /// <exception cref="NotImplementedException"></exception>
            public async Task Set(string key, object value, TimeSpan cacheTime)
            {
                if (value != null)
                {
                    if (value is string cacheValue)
                    {
                        // 字符串无需序列化
                       await database.StringSetAsync(key, cacheValue, cacheTime);
                    }
                    else
                    {
                        //序列化,将object值生成RedisValue
                        await database.StringSetAsync(key, JsonSerializer.Serialize(value), cacheTime);
                    }
                }
            }
        }
    View Code
  • 注入相关的接口,和Redis
    //接口
    builder.Services.AddSingleton<IRedisCaching,RedisCaching>();
    //Redis
    builder.Services.AddSingleton<ConnectionMultiplexer>(sp =>
    {
        //获取连接字符串
        string redisConfiguration = "127.0.0.1:6678,password=123456";
        var configuration = ConfigurationOptions.Parse(redisConfiguration, true);
        configuration.ResolveDns = true;
        return ConnectionMultiplexer.Connect(configuration);
    });
  • 使用Autofac将AOP文件注册到服务的程序集中
               var assemblysServicesPath = Path.Combine(basePath, "DogService");
    
                builder.RegisterType<LogAOP>();//可以直接替换其他拦截器!一定要把拦截器进行注册
                builder.RegisterType<RedisAOP>();
    
                //注入仓储
                var assemblysRepository = Assembly.LoadFrom(assemblysRepositoryPath);
                builder.RegisterAssemblyTypes(assemblysRepository)
                          .AsImplementedInterfaces()//方法表示将组件以其实现的接口类型进行注册,这样在进行依赖注入时,可以根据接口类型获取相应的实现类
                          .PropertiesAutowired()//方法用于自动装配属性依赖
                          .InstancePerDependency()//方法表示每次请求时都创建一个新的实例。
                          .EnableInterfaceInterceptors()//方法启用接口拦截,使得后续可以对注册的接口进行拦截。
                          .InterceptedBy(typeof(LogAOP),typeof(RedisAOP));//表

     

 

完活!

 

标签:缓存,string,Redis,arg,redis,key,AOP,invocation
From: https://www.cnblogs.com/zhang-3/p/17588502.html

相关文章

  • ehcache模糊批量移除缓存
    目录前言实现总结前言众所周知,encache是现在最流行的java开源缓存框架,配置简单,结构清晰,功能强大。通过注解@Cacheable可以快速添加方法结果到缓存。通过@CacheEvict可以快速清除掉指定的缓存。但由于@CacheEvict注解使用的是key-value的,不支持模糊删除,就会遇到问......
  • Redis从入门到放弃(3):发布与订阅
    1、介绍Redis是一个快速、开源的内存数据库,支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。除了基本的数据存储和检索功能外,Redis还提供了许多高级功能,其中之一就是发布订阅(Pub/Sub)。发布订阅是一种消息传递模式,它允许消息的发布者(发布者)将消息发送给多个订阅者(订阅......
  • docker-部署redis
    第一步:pull一个redis最新镜像Dockerpullredis第二步:启动一个主redis容器端口6379+挂载dockerrun--restart=always--log-optmax-size=100m--log-optmax-file=2-p6379:6379--nameredis-master-v/DockerContainerProperties/redis/redis-master.conf:/etc/redis......
  • 65.oracle中查看缓存命中率
    DBBlockGets:请求的数据块在buffer能满足的个数当前模式块意思就是在操作中正好提取的块数目,而不是在一致性读的情况下而产生的块数。正常的情况下,一个查询提取的块是在查询开始的那个时间点上存在的数据块,当前块是在这个时刻存在的数据块,而不是在这个时间点之前或者之后的数据......
  • AOP
    一、AOP1.AOPAspectOrientedProgramming(面向切面编程,面向方面编程),其实就是面向特定方法编程。2.场景(1)部分功能运行较慢,定位执行耗时较长的业务方法,此时需要统计每一个业务方法的执行耗时(2)记录操作日志(3)权限控制(4)事务管理4.优势(1)代码无侵入(2)减少重复代码(3)提升开发效率......
  • Redis 简介
    1、问题:2、Redis介绍2.1 redis是什么?2.2那Redis不是什么?2.3 Redis性能:2.4 Redis的功能:3、数据结构3.1Key3.2String3.3Hash3.4List3.5Set3.6SortedSet3.7事务3.8过期数据清除4、redis排序简介4.1 以下是对list按key排序的示例:4.2 一般SORT用法4.3 ......
  • Redis 持久化
    RDB快照(RedisDataBase)RDB是一种快照存储持久化方式,具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中,默认保存的文件名为dump.rdb,而在Redis服务器启动时,会重新加载dump.rdb文件的数据到内存当中恢复数据。开启RDB持久化方式开启RDB持久化方式很简单,客户端可以通过向Redis服......
  • ubuntu22 redis 6.0.16
    一、安装下载安装更新软件库aptupdate下载安装sudoaptinstallredis-server-y查看是否运行sudosystemctlstatusredis-serverActive:active(running)sinceFri2023-05-1912:56:25CST;3min19sago测试redis-cli127.0.0.1:6379>keys*(emptyarray)exit二、配置配......
  • Redis 主从同步原理
    一、什么是主从同步?主从同步,就是将数据冗余备份,主库(Master)将自己库中的数据,同步给从库(Slave)。从库可以一个,也可以多个,如图所示:二、为什么需要主从同步?Redis虽然有RDB和AOF持久化技术,可以在服务器重启的情况下保证内存中的数据不会丢失(但不意味着数据不丢,重启的时候还是......
  • Hibernate4的二级缓存
    [color=red][b]Hibernate4.1.4配置二级缓存EHCache步骤[/b][/color][url]http://www.vzhang.net/thread-81-1-1.html[/url]Hibernate4之二级缓存[url]http://zhou137520.iteye.com/blog/1611623[/url]Hibernate4的一些总结[url]http://1194867672-qq-com......