1. 事件总线
在我们的一个应用中,经常会出现一个逻辑执行之后要跟随执行另一个逻辑的情况,例如一个用户创建了后续还需要发送邮件进行通知,或者需要初始化相应的权限等。面对这样的情况,我们当然可以顺序进行相应的逻辑代码的编写,但这样会导致各种业务逻辑全部集中耦合在一个类中,违背了 "单一职责原则"。
在 ABP 框架中,对于上面的业务场景的处理,我们可以通过事件总线来解耦,使得代码逻辑实现更加清晰。事件总线的本质就是中介者模式,利用一个中介角色在发送方和接受方之间进行消息的传递,接受方单独实现关注的独立的小功能点,从而达到各块业务逻辑清晰,代码松散耦合的目的。
ABP 框架中的事件总线分为 本地事件总线 和 分布式事件总线 两种,两种使用的方式基本类似,只是分布式事件总线需要借助 RabbitMQ、Kafaka 等第三方消息队列中间件。本章先讲本地事件总线相关知识点。
2. 本地事件总线
本地事件总线实现进程内的事件的发布订阅功能,通常运用于单体应用架构或微服务架构中的一个服务内部。使用方式比较简单,以下是演示,也将通过控制台程序来进行。
2.1. 事件总线基本使用
本地事件总线的实现包含在 Volo.Abp.EventBus Nuget 包中,我们可以通过以下方式来集成。
通过以下命令创建一个控制台项目:
abp new AbpEventBus -t console
在 AbpEventBusSample.csproj 执行以下命令:
Abp add-package Volo.Abp.EventBus
如果是 Web 应用的话,在通过 ABP CLI 初始化启动模板的时候就已经集成了事件总线模块,无须再自己进行集成。
2.1.1 发布
ABP 提供了 ILocalEventBus 接口来满足我们对本地事件总线的使用。我们只需要在要进行事件发布的类注入该接口即可,之后就能通过以下的方式进行事件的发布了。
public class HelloWorldService : ITransientDependency
{
private readonly ILocalEventBus _localEventBus;
public HelloWorldService(ILocalEventBus localEventBus)
{
_localEventBus = localEventBus;
}
public Task SayHelloAsync()
{
// 当前业务逻辑
Console.WriteLine("Hello Jerry!");
// 关联业务逻辑
_localEventBus.PublishAsync(new HelloEventData
{
Who = "Tom",
ToWho = "Jerry",
Where = "广州天河正佳广场",
When = DateTime.Now
});
return Task.CompletedTask;
}
}
在进行事件发布之前需要先定义一个事件对象,这是一个普通类,是事件相关的各种数据的一个包装类,例如上面使用到的 HelloEventData 。
public class HelloEventData
{
public string Who { get; set; }
public string ToWho { get; set; }
public string Where { get; set; }
public DateTime When { get; set; }
}
就算在事件发布过程中不需要传输任何数据也需要创建一个类,在这种情况下为空类,这是因为事件总线是通过这个事件对象的类型来确定其对于的订阅者,从而执行相应的处理方法的。