结合 AOP 轻松处理事件发布处理日志
结合 AOP 轻松处理事件发布处理日志
Intro
前段时间,实现了 EventBus 以及 EventQueue 基于 Event 的事件处理,但是没有做日志(EventLog)相关的部分,原本想增加两个接口, 处理事件发布日志和事件处理日志,最近用了 AOP 的思想处理了 EntityFramework 的数据变更自动审计,于是想着事件日志也用 AOP 的思想来实现,而且可能用 AOP 来处理可能会更好一些,最近自己造了一个 AOP 的轮子 —— FluentAspects,下面的示例就以它来演示了,你也可以换成自己喜欢的 AOP 组件,思想是类似的
事件日志示例
事件发布日志
事件发布日志只需要拦截事件发布的方法调用即可,在发布事件时进行拦截,在拦截器中根据需要进行日志记录即可
事件发布者接口定义:
public interface IEventPublisher
{/// <summary>/// publish an event/// </summary>/// <typeparam name="TEvent">event type</typeparam>/// <param name="event">event data</param>/// <returns>whether the operation succeed</returns>bool Publish<TEvent>(TEvent @event) where TEvent : class, IEventBase;/// <summary>/// publish an event async/// </summary>/// <typeparam name="TEvent">event type</typeparam>/// <param name="event">event data</param>/// <returns>whether the operation succeed</returns>Task<bool> PublishAsync<TEvent>(TEvent @event) where TEvent : class, IEventBase;
}
事件发布日志拦截器:
public class EventPublishLogInterceptor : AbstractInterceptor
{public override async Task Invoke(IInvocation invocation, Func<Task> next){Console.WriteLine("-------------------------------");Console.WriteLine($"Event publish begin, eventData:{invocation.Arguments.ToJson()}");var watch = Stopwatch.StartNew();try{await next();}catch (Exception ex){Console.WriteLine($"Event publish exception({ex})");}finally{watch.Stop();Console.WriteLine($"Event publish complete, elasped:{watch.ElapsedMilliseconds} ms");}Console.WriteLine("-------------------------------");}
}
事件处理日志
事件处理器接口定义:
public interface IEventHandler
{Task Handle(object eventData);
}
事件处理日志拦截器定义:
public class EventHandleLogInterceptor : IInterceptor
{public async Task Invoke(IInvocation invocation, Func<Task> next){Console.WriteLine("-------------------------------");Console.WriteLine($"Event handle begin, eventData:{invocation.Arguments.ToJson()}");var watch = Stopwatch.StartNew();try{await next();}catch (Exception ex){Console.WriteLine($"Event handle exception({ex})");}finally{watch.Stop();Console.WriteLine($"Event handle complete, elasped:{watch.ElapsedMilliseconds} ms");}Console.WriteLine("-------------------------------");}
}
AOP 配置
Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(builder =>{builder.UseStartup<Startup>();}).UseFluentAspectServiceProviderFactory(options =>{// 拦截器配置// 拦截 `IEventPublisher` 日志,注册事件发布日志拦截器options.InterceptType<IEventPublisher>().With<EventPublishLogInterceptor>();// 拦截 `IEventHandler`,注册事件处理日志拦截器options.InterceptType<IEventHandler>().With<EventHandleLogInterceptor>();}, builder =>{// 默认使用默认实现来生成代理,现在提供了 Castle 和 AspectCore 的扩展,也可以自己扩展实现自定义代理生成方式// 取消注释使用 Castle 来生成代理//builder.UseCastleProxy();}, t => t.Namespace?.StartsWith("WeihanLi") == false // 要忽略的类型断言).Build().Run();
More
事件发布示例,定义了一个发布事件的中间件:
// pageView middleware
app.Use((context, next) =>
{var eventPublisher = context.RequestServices.GetRequiredService<IEventPublisher>();eventPublisher.Publish(new PageViewEvent(){Path = context.Request.Path.Value,});return next();
});
事件处理示例是用一个消息队列的模式来处理的,示例和前面的事件的文章类似,EventConsumer
是一个后台任务,完整代码示例如下:
public class EventConsumer : BackgroundService
{private readonly IEventQueue _eventQueue;private readonly IEventHandlerFactory _eventHandlerFactory;public EventConsumer(IEventQueue eventQueue, IEventHandlerFactory eventHandlerFactory){_eventQueue = eventQueue;_eventHandlerFactory = eventHandlerFactory;}protected override async Task ExecuteAsync(CancellationToken stoppingToken){while (!stoppingToken.IsCancellationRequested){var queues = await _eventQueue.GetQueuesAsync();if (queues.Count > 0){await queues.Select(async q =>{var @event = await _eventQueue.DequeueAsync(q);if (null != @event){var handlers = _eventHandlerFactory.GetHandlers(@event.GetType());if (handlers.Count > 0){await handlers.Select(h => h.Handle(@event)).WhenAll();}}}).WhenAll();}await Task.Delay(1000, stoppingToken);}}
}
完整的示例代码可以从https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/AspNetCoreSample 获取
OverMore
之前在微软的 EShopOnContainers 项目里又看到类似下面这样的代码,在发布事件的时候包装一层 try ... catch 来记录事件发布日志,相比之下,本文示例中的这种方式更为简洁,代码更清爽
Reference
https://www.cnblogs.com/weihanli/p/12941919.html
https://www.cnblogs.com/weihanli/p/implement-event-queue.html
https://github.com/WeihanLi/WeihanLi.Common
https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/AspNetCoreSample/Startup.cs
结合 AOP 轻松处理事件发布处理日志相关推荐
- 十、springboot注解式AOP(@Aspect)统一日志管理
springboot注解式AOP(@Aspect)统一日志管理 简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功 ...
- springboot aop + logback + 统一异常处理 打印日志
springboot aop + logback + 统一异常处理 打印日志 参考文章: (1)springboot aop + logback + 统一异常处理 打印日志 (2)https://ww ...
- JPOM - AOP+自定义注解实现操作日志记录
文章目录 地址 版本 源码解析-AOP+自定义注解实现操作日志记录 地址 Gitee: https://gitee.com/dromara/Jpom 官网: https://jpom.io/ 一款简而 ...
- spring AOP自定义注解方式实现日志管理
转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接 ...
- 【经典】Spring aop切面实现异步添加日志—完整版
系统开发中我们常遇到要处理系统日志等信息的,在此我分享一篇 利用spring aop切面来异步添加日志的操作,其中用到了 队列和多线程,前面的博客有写. 第一步:创建log实体,根据自己业务而定, p ...
- SpringBoot切面AOP打印请求和响应日志
1.说明 Spring Boot微服务对外开放的Restful接口, 为了方便定位问题, 一般需要记录请求日志和响应日志, 而在每个接口中开发日志代码是非常繁琐的, 本文介绍使用Spring的切面AO ...
- 启明星辰泰合发布新一代日志分析系统
发布时间:2016-01-12 作者:启明星辰 伴随着大数据时代的到来,启明星辰于2015年12月25日正式对外发布了面向企业级客户.融合大数据技术的新一代日志分析与审计平台(以下简称TSOC-S ...
- 使用AOP与注解记录Java日志
有些时候,我想要把每个运行过的方法接收到的参数.返回值和执行时间等信息记录(通过slf4j 和 log4j)下来.在AspectJ.jcabi-aspects和Java注解的帮助下我实现了这个想法. ...
- Spring Boot中使用AOP统一处理Web请求日志
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...
最新文章
- mysql数据库支持的锁粒度包括_1. Mysql的并发(锁策略、锁粒度、事务)
- Influxdb1.2.2安装
- 这是我的第一个python程序怎么打-我的第一个Python程序
- python数组加入新元素_Python之list添加新元素、删除元素、替换元素
- MVC5+EF6 入门完整教程 总目录
- Android NDK调试定位错误
- Eclipse里web的依赖工程部署的简便方法
- 开发团队测试的难与易
- 一张图看懂阿里云网络产品[十一]云托付
- 无向图中两点之间的距离_自然语言处理中距离计算总结
- java链表的用法_数据结构(java语言描述)链表的使用
- 细说Oracle11g RAC的IP地址
- 生成对抗网络系列—ACL-GAN
- ES6面试题(参考文档)
- 读书笔记系列2:《More Effective C++》
- 两阶段最小二乘法原理_两阶段最小二乘法第一阶段为什么加入原模型外生变量...
- 编程算法 - 最好牛线(Best Cow Line) 代码(C)
- 认识植物 - 水杉 (比较常见的濒危植物)
- 基于STM32F407的人脸追踪
- 银行项目外包专题系列之二:公司没提升打杂,裸辞后收到银行外包,到底去还是不去