petshop异时消息处理队列抽象工厂

张逸老师说的,异时消息处理队列为什么设置成抽象工厂是这样的:

/********************************************************************/

考虑到IOrder的实现有可能的变化,PetShop仍然利用了工厂模式,将IOrder对象的创建用专门的工厂模块进行了封装:

在类QueueAccess中,通过CreateOrder()方法利用反射技术创建正确的IOrder类型对象:
    public static PetShop.IMessaging.IOrder CreateOrder() 
    {
        string className = path + ".Order";
        return PetShop.IMessaging.IOrder)Assembly.Load(path).CreateInstance(className);
    }
path的值通过配置文件获取:
private static readonly string path = ConfigurationManager.AppSettings["OrderMessaging"];
而配置文件中,OrderMessaging的值设置如下:
<add key="OrderMessaging" value="PetShop.MSMQMessaging"/>
之所以利用工厂模式来负责对象的创建,是便于在业务层中对其调用,例如在BLL模块中OrderAsynchronous类:
public class OrderAsynchronous : IOrderStrategy
{        
    private static readonly PetShop.IMessaging.IOrder asynchOrder = PetShop.MessagingFactory.QueueAccess.CreateOrder();
    public void Insert(PetShop.Model.OrderInfo order) 
    {
        asynchOrder.Send(order);
    }
}
一旦IOrder接口的实现发生变化,这种实现方式就可以使得客户仅需要修改配置文件,而不需要修改代码,如此就可以避免程序集的重新编译和部署,使得系统能够灵活应对需求的改变。例如定义一个实现IOrder接口的SpecialOrder,则可以新增一个模块,如PetShop.SpecialMSMQMessaging,而类名则仍然为Order,那么此时我们仅需要修改配置文件中OrderMessaging的值即可:
<add key="OrderMessaging" value="PetShop.SpecialMSMQMessaging"/>

/**************************************************************************/

这么一大段我以为重点就是加红的那些文字。如果是这样的话我倒是可以理解。

先不管那么多,我觉得这个异时消息队列你的代码我还有许多迷惑,先一一记录下来吧:

考虑到扩展性他们把MSMQ的处理机制封装在PetShopQueue类里。PetShopQueue继承了IDisposable接口,IDisposable接口的主要用途是释放非托管资源。

唯一的方法是Dispose()。来看看PetShopQueue是怎么利用这接口的吧:

public void Dispose() {
            queue.Dispose();//queue是MessagingQueue的实例对象
}

自己下午查找MSDN把一些不懂的类都注释了,先贴出来看下:

1 publicclass PetShopQueue : IDisposable {
2 //MessageQueueTransactionType指定消息队列事务的类型。
//MessageQueueTransactionType.Automatic(如果已有 MTS 事务上下文,将在发送或接收消息时使用它。)

3  protected MessageQueueTransactionType transactionType = MessageQueueTransactionType.Automatic;
4 protected MessageQueue queue;
5 protected TimeSpan timeout;// 对象的值是等于所表示时间间隔的刻度数。一个刻度等于 100 纳秒,就是设定一个时间间隔MSMQ就会自动检查队列,有没有需要插入Order和Invertory的资源。
6  
7 public PetShopQueue(string queuePath, int timeoutSeconds) {
8 queue =new MessageQueue(queuePath);//构造函数,指定所使用的消息队列
9   timeout = TimeSpan.FromSeconds(Convert.ToDouble(timeoutSeconds));
10
11 // Performance optimization since we don't need these features
12   queue.DefaultPropertiesToSend.AttachSenderId =false;//该值指示发送方 ID 不用附在消息中。
13   queue.DefaultPropertiesToSend.UseAuthentication =false;//如果发送应用程序请求对消息进行验证,则为 true;否则为 false。默认为 false
14   queue.DefaultPropertiesToSend.UseEncryption =false;//要求消息队列加密消息时为 true;否则为 false。默认为 false。
15   queue.DefaultPropertiesToSend.AcknowledgeType = AcknowledgeTypes.None;//此值用于确定系统在管理队列中传递的确认消息的类型以及向发送应用程序返回确认消息的时间。默认为 AcknowledgeTypes.None。
16   queue.DefaultPropertiesToSend.UseJournalQueue =false;//要求在消息成功地从发件计算机传送到下一步后,将消息的副本保存在发件计算机的计算机日记中时为 true,否则为 false。默认为 false
17   }
18
19 ///<summary>
20 /// Derived classes call this from their own Receive methods but cast
21 /// the return value to something meaningful.
22 ///</summary>
23  publicvirtualobject Receive() {
24 try {
25 //接收 MessageQueue 引用的队列中可用的第一条消息。此调用是同步的,并且一直等到队列中有可用的消息或超时到期
26  using (Message message = queue.Receive(timeout, transactionType))
27 return message;
28 }
29 catch (MessageQueueException mqex) {
//接收或查看消息超时时间已到的处理机制。
30 if (mqex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
31 thrownew TimeoutException();
32
33 throw;
34 }
35 }

以上比较不懂的就是MessageQueueTransactionType这个事物类型了,他是个枚举吧,有三种情况,none、single和AutoMatic。

注意到,PetShopQueue定义了消息Receive是virtual重写方法。在Order子类却是用new对其进行重写,根据多态的机制,

new重写的话假如我们这样做吧:

PetShopQueue  A=new Order();

A.Receive();调用的还是A自己的Receive()方法。

/**********************************************************************************/

在自己啰嗦下petshop采用的是面向接口的编程思想,所以调用方法的时候要这样做(一个例子):

IOrder order=new Order();

/***********************************************************************************/

接下来就是Order的研究了,这个弄懂了,模块二就算ok了,今晚就做别的。呵呵。

1 publicclass Order : PetShopQueue, PetShop.IMessaging.IOrder {
2
3 // Path example - FormatName:DIRECT=OS:MyMachineName\Private$\OrderQueueName
4  privatestaticreadonlystring queuePath = ConfigurationManager.AppSettings["OrderQueuePath"];
5 privatestaticint queueTimeout =20;//在PetShopQueue设置了timeout值,OrderProcessor会根据timeout值定期扫描队列中的订单数据。
6  
7 public Order() : base(queuePath, queueTimeout) {
8 queue.Formatter =new BinaryMessageFormatter();//使用二进制格式,将一个对象(或连接的对象的整个图形)序列化成“消息队列”消息体或从“消息队列”消息体反序列化一个对象。
9   }
10
11
12 /// 这个方法是用new重写的
13  publicnew OrderInfo Receive() {
14 // This method involves in distributed transaction and need Automatic Transaction type
15 //将上面的英语谷歌翻译下是:这种方法涉及到分布式事务,需要Automatic事务类型,怎么看出分布式?分布式就用Automatic?
16  base.transactionType = MessageQueueTransactionType.Automatic;
17 return (OrderInfo)((Message)base.Receive()).Body;
18 }
19 /// 这个方法是IOder接口定义的,在petShopQueue中并没有对其进行定义
20  public OrderInfo Receive(int timeout) {
21 base.timeout = TimeSpan.FromSeconds(Convert.ToDouble(timeout));
22 return Receive();
23 }
24
25 ///<summary>
26 /// Method to send asynchronous order to Pet Shop Message Queue
27 ///</summary>
28  publicvoid Send(OrderInfo orderMessage) {
29 // This method does not involve in distributed transaction and optimizes performance using Single type
30  base.transactionType = MessageQueueTransactionType.Single;
31 base.Send(orderMessage);
32 }
33 }

两个地方不太理解,其一是行3那段注释,根据MSDN的注释是:对于专用队列为 MachineName\Private$\QueueNameFormatName 属性允许对消息队列进行脱机访问。

还有就是Receive()这个方法了,这个方法有两重性,即是继承接口又是继承PetShopQueue的。

不理解的是行17的转换,是不是MessageQueue传来的消息都要经过Messagg的转换,才可读取消息?如果是就没有问题了。

刚刚看到张逸老师的解释跟我想的是一样的(关于Message)。

 

原文地址:https://www.cnblogs.com/huaizuo/p/2101933.html