0. 前言

之前写了几篇文章介绍了一些AOP的知识,

但是还没有亮出来AOP的姿势,

也许姿势漂亮一点,

大家会对AOP有点兴趣

内容大致会分为如下几篇:(毕竟人懒,一下子写完太累了,没有动力)

  1. AOP的姿势之 简化 MemoryCache 使用方式
  2. AOP的姿势之 简化混用 MemoryCache 和 DistributedCache 使用方式
  3. AOP的姿势之 如何把 HttpClient 变为声明式

至于AOP框架在这儿示例依然会使用我自己基于emit实现的动态代理AOP框架: https://github.com/fs7744/Norns.Urd

毕竟是自己写的,魔改/加功能都很方便,

万一万一大家如果有疑问,(虽然大概不会有),我也好回答, (当然如果大家认可,在github给个star,就实在是太让人开心了)

1. 正文

1.1 回顾 MemoryCache如何使用

var cache = ServiceProvider.GetRequiredService<IMemoryCache>();
var r = await cache.GetOrCreateAsync(cacheKey, async e =>
{
var rr = await do();
e.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow;
return rr;
});

MemoryCache 本身已经被封装到如此简单就可以使用了

但是呢,每次我们使用的时候依然要这样重复写类似的代码

当然我们都是拥有超强的 ctrl+c 和 ctrl+v 能力,

这点点重复代码都是些毛毛雨啦,

上w行代码一把梭都是小场面了,

不过呢,这样的代码写的和在校的学生一样,

怎么能体现我们混迹江湖,加班数十载的逼格呢?

我们要让这些在校学生/实习生看不懂我们的代码,

让他们看不到GetOrCreateAsync

让他们调试的时候 do() 里面的断点跑不到

这样我们才能展示出扫地僧的实力:来,小朋友,我来教你新姿势

1.2 逼格启航

1.2.1 逼格核心 - 拦截器

在Norns.Urd中,Interceptor 拦截器是用户可以在方法插入自己的逻辑的核心。

标准结构为IInterceptor

public interface IInterceptor
{
// 用户可以通过Order自定义拦截器顺序,排序方式为ASC,全局拦截器和显示拦截器都会列入排序中
int Order { get; } // 同步拦截方法
void Invoke(AspectContext context, AspectDelegate next); // 异步拦截方法
Task InvokeAsync(AspectContext context, AsyncAspectDelegate next); // 可以设置拦截器如何选择过滤是否拦截方法,除了这里还有NonAspectAttribute 和全局的NonPredicates可以影响过滤
bool CanAspect(MethodInfo method);
}

这里我们为了大家理解简单,就使用最简单的方式来做 : 使用 AbstractInterceptorAttribute

一个非常简单的例子就如下了:

    public class CacheAttribute : AbstractInterceptorAttribute
{
private readonly TimeSpan absoluteExpirationRelativeToNow;
private readonly string cacheKey; // 为了简单,缓存策略我们就先只支持TTL 存活固定时间
public CacheAttribute(string cacheKey, string absoluteExpirationRelativeToNow)
{
this.cacheKey = cacheKey;
this.absoluteExpirationRelativeToNow = TimeSpan.Parse(absoluteExpirationRelativeToNow);
} public override async Task InvokeAsync(AspectContext context, AsyncAspectDelegate next)
{
// 整个代码基本和我们直接使用 MemoryCache 一样
var cache = context.ServiceProvider.GetRequiredService<IMemoryCache>();
var r = await cache.GetOrCreateAsync(cacheKey, async e =>
{
await next(context); // 所以真正实现的方法逻辑都在 next 中,所以调用它就好了
e.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow;
return context.ReturnValue; // 结果都在ReturnValue , 这里为了简单,就不写 void / Task<T> / ValueTask<T> 等等 各种返回值的兼容代码了
});
context.ReturnValue = r; // 设置 ReturnValue, 由于缓存有效期内, next不会被调用, 所以ReturnValue不会有值,我们需要将缓存结果设置到 ReturnValue
}
}

1.2.2 测试一下

 public interface ITestCacheClient
{
string Say(string v);
} public class TestCacheClient : ITestCacheClient
{
public string Say(string v) => v;
} static class Program
{
static void Main(string[] args)
{
var client = new ServiceCollection()
.AddMemoryCache()
.AddSingleton<ITestCacheClient, TestCacheClient>()
.ConfigureAop()
.BuildServiceProvider()
.GetRequiredService<ITestCacheClient>();
Console.WriteLine(client.Say("Hello World!"));
Console.WriteLine(client.Say("Hello Two!"));
Thread.Sleep(3000);
Console.WriteLine(client.Say("Hello Two!"));
}
}

Console 结果

Hello World!
Hello Two!
Hello Two!

加上缓存设置:

    public class TestCacheClient : ITestCacheClient
{
[Cache(nameof(Say), "00:00:03")]
public string Say(string v) => v;
}

再次测试的 Console 结果

Hello World!
Hello World!
Hello Two!

例子代码都在 https://github.com/fs7744/AopDemoList/tree/master/MakeMemoryChacheSimple

处理情况更全面的例子在 https://github.com/fs7744/Norns.Urd/tree/main/src

祝大家都能愉快被叫 大神 nb。

AOP的姿势之 简化 MemoryCache 使用方式的更多相关文章

  1. AOP的姿势之 简化混用 MemoryCache 和 DistributedCache 的方式

    0. 前言 之前写了几篇文章介绍了一些AOP的知识, 但是还没有亮出来AOP的姿势, 也许姿势漂亮一点, 大家会对AOP有点兴趣 内容大致会分为如下几篇:(毕竟人懒,一下子写完太累了,没有动力) AO ...

  2. 6.AOP配置与应用(xml的方式)

    xml 配置 AOP 1.将 拦截其器对象 初始化到容器中 2.<aop:config> <aop:aspect.... <aop:pointcut <aop:befor ...

  3. AOP的具体实践-简化结果返回的处理

    原因: 以前学习Spring的时候着重学习过AOP概念,但是一直也没有用上,唯一碰到过的就是Spring内置的事务管理.现在碰到过一些结果后面的操作适合用到,所以这里就拿出来用一下,并且复习一下落下的 ...

  4. SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP

    AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...

  5. Dora.Interception,为.NET Core度身打造的AOP框架 [2]:以约定的方式定义拦截器

    上一篇<更加简练的编程体验>提供了最新版本的Dora.Interception代码的AOP编程体验,接下来我们会这AOP框架的编程模式进行详细介绍,本篇文章着重关注的是拦截器的定义.采用“ ...

  6. Java 中 AOP —— 探讨其存在价值及实现方式对比

    AOP 概述 Aspect-oriented programming(面向切面编程).最广为人知的面向侧面的程序设计语言是由施乐帕洛阿尔托研究中心 (施乐帕克 nb!)开发的AspectJ,该语言可以 ...

  7. 【学习】Spring 的 AOP :基于Annotation 的“零配置”方式

    转自:http://www.cnblogs.com/jbelial/archive/2012/07/20/2539123.html AOP(Aspect Orient Programming ) , ...

  8. Spring 详解(二)------- AOP关键概念以及两种实现方式

    目录 1. AOP 关键词 2. AOP 的作用 3. AOP 的通知类型 4. 基于 xml 的配置方式 5. 基于注解的配置方式 6. 切面的优先级 7. 重用切点表达式 8. 两种方式的比较(摘 ...

  9. Spring的AOP开发(基于AspectJ的XML方式)

    Spring的AOP的简介: AOP思想最早是由AOP联盟组织提出的.Spring是使用这种思想最好的框架 Spring的AOP有自己实现的方式(非常繁琐). Aspect是一个AOP的框架, Spr ...

随机推荐

  1. C++重复结构题解

    买房子 总时间限制:  1000ms 内存限制:  65536kB 描述 某程序员开始工作,年薪N万,他希望在中关村公馆买一套60平米的房子,现在价格是200万,假设房子价格以每年百分之K增长,并且该 ...

  2. 【linux】i2c使用分析&源码实战

    目录 前言 1. 设备检查命令 1.1 查看I2C驱动 1.2 i2c-tools 1.2.1 I2C-detect安装 1.2.2 i2cdetect 命令 1.2.3 i2cget 命令 1.2. ...

  3. [自学] MIT的EECS本科+研究生课程【持续更新中-2020.06.02】

    前言 我的本科是读的电子信息工程,研究生跟着老师做项目,参与到深度学习中来,毕业后做了算法工程师,工作之后愈发发现,不论从事什么岗位,基础都很重要,但现在也没有时间再读一遍本科了,自学的话也不知道从何 ...

  4. 基于vue(element ui) + ssm + shiro 的权限框架

    zhcc 基于vue(element ui) + ssm + shiro 的权限框架 引言 心声 现在的Java世界,各种资源很丰富,不得不说,从分布式,服务化,orm,再到前端控制,权限等等玲琅满目 ...

  5. nodejs事件和事件循环简介

    目录 简介 事件 事件循环 事件循环的阻塞 事件循环举例 栈和消息队列 作业队列和promise process.nextTick() setImmediate() setInterval() 简介 ...

  6. PyQt(Python+Qt)入门:设计师中部件toolTip、statusTip、whatsThis的属性

    在Qt Designer中定义的部件,都有toolTip.statusTip.whatsThis,这些属性都是辅助提示的信息. toolTip toolTip属性设置部件的toolTip提示信息,to ...

  7. 自学linux——21. NFS服务器的搭建

    NFS服务器的搭建 1.NFS的认识 NFS(Network File System即网络文件系统)服务最大的功能就是可以透过网络,让不同的机器.不同的操作系统.可以彼此分享文件,可以将远程 Linu ...

  8. 查询时间倒退一天-项目中惊现神秘BUG-JsonFormat使用采坑记

    一.问题由来 前一天下午正在写代码的时候,领导突然走过来跟我说,让我去看一个神秘的BUG,说是在数据库中查询时的一个日期 返回到页面后,查询时间倒退了一天.一听到这个BUG,我就感觉很奇怪,还有这样的 ...

  9. element ui中表单循环项的校验

    注意:prop是动态的

  10. 题解-CF101D Castle

    题面 CF101D Castle 给一棵 \(n\) 个节点的带权树,求一种遍历方案,从 \(1\) 出发,每条边走两次,走过所有点,第一次经过每个节点的平均时间最小.输出这个平均时间. 数据范围:\ ...