一.nop事件机制简介
应用场景:客户支付成功后,需要发送短信、邮件告知客户订单支付成功(短信、邮件由不同模块实现)
实现方法: 1.定义支付成功OrderPaidEvent事件。
2.定义短信,邮箱两个消费者共同监听OrderPaidEvent事件,并实现相关业务。
3.当客户支付成功后生产者发送OrderPaidEvent事件。
4.消费者接收到OrderPaidEvent事件后,短信和邮箱消费者分别执行自己的业务。
nop事件机制使用到“生产者/消费者”模式。生产者只负责发布事件,并不需要关心谁来处理,相反消费者只用来处理事件。那生产者和消费者是如何进行关联的呢?nop实现是非常简单的,通过泛型来定义一个事件类,如果生产者和消费者都使用同一个事件类,那么就关联到一起了称之为订阅。负责实现事件机制的部分称之为缓冲区,缓冲区的作用是通过解耦的方式实现消息机制。生产者和消费者是一对多的关系。下图简单介绍下生产者消费者关系。
二.nop事件相关接口
生产者接口:Nop.Services.Events.IEventPublisher
消费者接口:Nop.Services.Events.IConsumer<T>
事件订阅接口:Nop.Services.Events.ISubscriptionService
IEventPublisher接口Publish<T>(T eventMessage)方法用于发布事件(生产者)。
IConsumer<T>接口HandleEvent(T eventMessage)方法用于处理事件(消费者)。
两者之间的关系由T泛型来关联,称之为事件,简单的说T类型相同则两者关联订阅成功。
ISubscriptionService接口GetSubscriptions<T>()方法返回IList<IConsumer<T>>集合,该集合保存了消费者。
接口实现如下图:
EventPublisher
1 using System.Collections.Generic; 2 using Nop.Core.Infrastructure; 3 4 namespace Nop.Services.Events 5 { 6 /// <summary> 7 /// 事件订阅服务 8 /// </summary> 9 public class SubscriptionService : ISubscriptionService 10 { 11 /// <summary> 12 /// 获取事件订阅 13 /// </summary> 14 /// <typeparam name="T">Type</typeparam> 15 /// <returns>Event consumers</returns> 16 public IList<IConsumer<T>> GetSubscriptions<T>() 17 { 18 return EngineContext.Current.ResolveAll<IConsumer<T>>(); 19 } 20 } 21 } 22
二.消费者IConsermer<T>注册
应用启动时Nop.Web.Framework.DependencyRegistrar中将所有实现IConsumer<T>接口的类注册到ioc容器中。
通过EngineContext.Current.ResolveAll<IConsumer<T>>(),就可以获取到某个消息(T)的订阅了。
1 //注册事件消费者 2 var consumers = typeFinder.FindClassesOfType(typeof(IConsumer<>)).ToList(); 3 foreach (var consumer in consumers) 4 { 5 builder.RegisterType(consumer) 6 .As(consumer.FindInterfaces((type, criteria) => 7 { 8 var isMatch = type.IsGenericType && ((Type)criteria).IsAssignableFrom(type.GetGenericTypeDefinition()); 9 return isMatch; 10 }, typeof(IConsumer<>))) 11 .InstancePerLifetimeScope(); 12 }
三.创建消费者
结合上边提到的应用场景,我们创建订阅OrderPaidEvent事件来处理短信通知的消费者。
创建OrderPaidSMSEventConsumer类
1 using System; 2 using Nop.Core; 3 using Nop.Core.Domain.Orders; 4 using Nop.Core.Plugins; 5 using Nop.Services.Events; 6 using Nop.Services.Orders; 7 8 namespace Nop.Plugin.SMS 9 { 10 public class OrderPaidSMSEventConsumer : IConsumer<OrderPaidEvent> 11 { 12 13 private readonly IOrderService _orderService; 14 15 public OrderPaidSMSEventConsumer( 16 IOrderService orderService, 17 IStoreContext storeContext) 18 { 19 this._orderService = orderService; 20 this._storeContext = storeContext; 21 } 22 23 /// <summary> 24 /// 事件处理. 25 /// </summary> 26 /// <param name="eventMessage">The event message.</param> 27 public void HandleEvent(OrderPaidEvent eventMessage) 28 { 29 30 var order = eventMessage.Order;//获取订单 31 32 //发送短息通知代码 33 //.................... 34 } 35 } 36 }
OrderPaidSMSEventConsumer类继承 IConsumer<OrderPaidEvent>,OrderPaidEvent就是事件类,维护生产者与消费者之间的订阅关系。事件类名称可以自定义,代表了一个事件。
接下来我们再创建一个邮件处理的消费者OrderPaidEmailEventConsumer类,同样继承了ICnsumer<OrderPaidEvent>,说明我们订阅的是也是OrderPaidEvent事件。
1 using System; 2 using Nop.Core; 3 using Nop.Core.Domain.Orders; 4 using Nop.Core.Plugins; 5 using Nop.Services.Events; 6 using Nop.Services.Orders; 7 8 namespace Nop.Plugin.Email 9 { 10 public class OrderPaidEmailEventConsumer : IConsumer<OrderPaidEvent> 11 { 12 13 private readonly IOrderService _orderService; 14 private readonly IStoreContext _storeContext; 15 16 public OrderPaidEmailEventConsumer( 17 IOrderService orderService, 18 IStoreContext storeContext) 19 { 20 21 this._orderService = orderService; 22 this._storeContext = storeContext; 23 } 24 25 /// <summary> 26 /// 邮件处理 27 /// </summary> 28 /// <param name="eventMessage">The event message.</param> 29 public void HandleEvent(OrderPaidEvent eventMessage) 30 { 31 32 33 var order = eventMessage.Order; 34 35 //发送邮件通知客户 36 //............................ 37 } 38 } 39 }
四.生产消息
我们已经创建了两个订阅了OrderPaidEvent事件的消费者,现在我们看看当客户支付完成时我们是如何通知消费者的。
Nop.Services.OrderProcessingService类中
_eventPublisher.Publish(new OrderPaidEvent(order))方法发送了OrderPaidEvent事件。这时候上边订阅OrderPaidEvent事件的消费(短信、邮件)就会处理消息了。
五.nop中常用的事件整理
消费者,主要还是处理缓存
Nop.Web.Infrastructure.Cache.ModelCacheEventConsumer:前台模型相关
Nop.Admin.Infrastructure.Cache.ModelCacheEventConsumer:后台模型相关
Nop.Services.Discounts.Cache.DiscountEventConsumer:折扣相关
Nop.Services.Catalog.Cache.PriceCacheEventConsumer:价格相关
Nop.Services.Customers.Cache.CustomerCacheEventConsumer:密码修改
生产者,下图总结了nop 3.9 源码中自带的事件及所在的类,大部分是未实现对应的消费者。
nop只是在相关的地方留下事件位置,方便我们二次开发的时候进行扩展。
六.总结
1.生产者需要继承IEventPublisher接口。
2.消费者需要继承IConsumer<T>接口。
3.消费者通过事件类订阅到生产者,订阅实现参见ISubscriptionService接口。
nop事件机制实现很简单,有兴趣的朋友可以用RabbitMQ进行消息的扩展。
文中有错误的理解和不正确的观点,请留言,一起交流共同进步。
本文地址:http://www.cnblogs.com/yaoshangjin/p/7234522.html
本文为大波浪原创、转载请注明出处。
如果您认为这篇文章还不错或者有所收获,可以点击下方的【关注】按钮,因为你的支持是我继续写作,分享的最大动力!
作者:大波浪
来源:http://www.cnblogs.com/yaoshangjin/
声明: 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果您发现博客中出现了错误,或者有更好的建议、想法,请及时与我联系!!如果想找我私下交流,可以私信或者加我QQ。
http://www.cnblogs.com/yaoshangjin/p/7234522.html