misc doc improvements

This commit is contained in:
markpollack
2008-08-15 02:10:25 +00:00
parent 9fac2a99e7
commit 9f4849f780
4 changed files with 125 additions and 31 deletions

View File

@@ -1571,21 +1571,33 @@ MyInterface myProxyObject2 = (MyInterface)ctx.GetObject("MyObject"); // Will ret
<title>Proxying mechanisms</title>
<para>Spring creates AOP proxies built at runtime through the use of the
TypeBuilder API. Two types of proxies can be created, composition based or
TypeBuilder API. </para>
<para>Two types of proxies can be created, composition based or
inheritance based. If the target object implements at least one interface
then a composition based proxy will be created, otherwise an inheritance
based proxy will be created. The composition based proxy is implemented by
creating a type that implements all the interfaces specified on the target
object. The actual class name of this dynamic type is 'GUID' like. A
private field holds the target object and the dynamic type implementation
will first execute any advice before or after making the target object
method call on the target object. The inheritance based mechanism creates
a dynamic type where that inherits from the target type. This lets you
downcast to the target type if needed. Please note that in both cases a
target method implementation that calls other methods on the target object
will not be advised. To force inheritance based proxies you should either
set the ProxyTargetType property of a ProxyFactory or the element
proxy-target-type when using an AOP schema based configuration.</para>
based proxy will be created. </para>
<para>The composition based proxy is implemented by creating a type that
implements all the interfaces specified on the target object. The actual
class name of this dynamic type is 'GUID' like. A private field holds the
target object and the dynamic type implementation will first execute any
advice before or after making the target object method call on the target
object. </para>
<para>The inheritance based mechanism creates a dynamic type where that
inherits from the target type. This lets you downcast to the target type
if needed. Please note that in both cases a target method implementation
that calls other methods on the target object will not be advised. To
force inheritance based proxies you should either set the
<classname>ProxyTargetType</classname> to true property of a ProxyFactory
or set the XML namespace element <classname>proxy-target-type =
true</classname> when using an AOP schema based configuration.</para>
<note>
<para>An important alternative approach to inheritance based proxies is
disucssed in the next section.</para>
</note>
<para>In .NET 2.0 you can define the assembly level attribute,
InternalsVisibleTo, to allow access of internal interfaces/classes to
@@ -1594,6 +1606,46 @@ MyInterface myProxyObject2 = (MyInterface)ctx.GetObject("MyObject"); // Will ret
InternalsVisibleTo("Spring.Proxy")] and [assembly:
InternalsVisibleTo("Spring.DynamicReflection")] to your to AssemblyInfo
file.</para>
<sect2 id="aop-inheritancebasedaopconfigurer">
<title>InheritanceBasedAopConfigurer</title>
<para>There is an important limitation in the inheritance based proxy as
described above, all methods that manipulate the state of the object
should be declared as virtual. Otherwise some method invocations get
directed to the private 'target' field member and others to the base
class. Winform object are an example of case where this approach does
not apply. To address this limitation, a new post-processing mechanism
was introduced in version 1.2 that creates a proxy type without the
private 'target' field. Interception advice is added directly in the
method body before invoking the base class method.</para>
<para>To use this new inheritance based proxy described in the note
above, declare an instance of the InheritanceBasedAopConfigurer, and
IObjectFactoryPostProcessor, in yoru configuraiton file. Here is an
example.</para>
<programlisting>&lt;object type="Spring.Aop.Framework.AutoProxy.InheritanceBasedAopConfigurer, Spring.Aop"&gt;
&lt;property name="ObjectNames"&gt;
&lt;list&gt;
&lt;value&gt;Form*&lt;/value&gt;
&lt;value&gt;Control*&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;property name="InterceptorNames"&gt;
&lt;list&gt;
&lt;value&gt;debugInterceptor&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;object id="debugInterceptor" type="AopPlay.DebugInterceptor, AopPlay"/&gt;</programlisting>
<para>This configuraiton style is similar to the autoproxy by name
approach described <link linkend="aop-nameautoproxy">here</link> and is
particuarly appropriate when you want to apply advice to WinForm
classes.</para>
</sect2>
</sect1>
<sect1 id="aop-prog">

View File

@@ -45,6 +45,7 @@
<!ENTITY tx-quickstart SYSTEM "tx-quickstart.xml">
<!ENTITY quartz-quickstart SYSTEM "quartz-quickstart.xml">
<!ENTITY nms-quickstart SYSTEM "nms-quickstart.xml">
<!ENTITY msmq-quickstart SYSTEM "msmq-quickstart.xml">
<!ENTITY wcf-quickstart SYSTEM "wcf-quickstart.xml">
<!ENTITY javadevelopers SYSTEM "javadevelopers.xml">
<!ENTITY misc SYSTEM "misc.xml">
@@ -376,6 +377,9 @@
<listitem>
<xref linkend="nms-quickstart" />
</listitem>
<listitem>
<xref linkend="msmq-quickstart" />
</listitem>
<listitem>
<xref linkend="wcf-quickstart" />
</listitem>
@@ -390,6 +394,7 @@
&tx-quickstart;
&quartz-quickstart;
&nms-quickstart;
&msmq-quickstart;
&wcf-quickstart;
</part>
<part id="index-javadevelopers">

View File

@@ -88,6 +88,9 @@
classes to write enterprise MSMQ applications than rolling your own
infrastructure. Feedback and new feature requests are always
welcome.</para>
<para>The Spring.MsmqQuickstart application located in the examples
directory of the distribution shows this functionality in action.</para>
</section>
<section>
@@ -427,6 +430,10 @@ void Send(MessageQueue messageQueue, Message message);</programlisting>
<classname>MessageQueueTemplate</classname>. The default value is
<classname>MessageQueue.InfiniteTimeout </classname>(which is actually
~3 months).</para>
<para>The XML configuration snippit for defining a MessageQueueTemplate
is shown in the previous section and also is located in the MSMQ
quickstart application configuraiton file Messaging.xml</para>
</section>
<section>
@@ -649,7 +656,6 @@ void Send(MessageQueue messageQueue, Message message);</programlisting>
<emphasis role="bold">&lt;!-- Delegate to plain .NET object for message handling --&gt;</emphasis>
&lt;object id="messageListenerAdapter" type="Spring.Messaging.Listener.MessageListenerAdapter, Spring.Messaging"&gt;
&lt;property name="DefaultResponseQueueName" value="msmqTestResponseQueue"/&gt;
&lt;property name="MessageConverterObjectName" value="messageConverter"/&gt;
&lt;property name="HandlerObject" ref="simpleHandler"/&gt;
&lt;/object&gt;
@@ -779,7 +785,6 @@ void Send(MessageQueue messageQueue, Message message);</programlisting>
<emphasis role="bold">&lt;!-- Delegate to plain .NET object for message handling --&gt;</emphasis>
&lt;object id="messageListenerAdapter" type="Spring.Messaging.Listener.MessageListenerAdapter, Spring.Messaging"&gt;
&lt;property name="DefaultResponseQueueName" value="msmqTestResponseQueue"/&gt;
&lt;property name="MessageConverterObjectName" value="messageConverter"/&gt;
&lt;property name="HandlerObject" ref="simpleHandler"/&gt;
&lt;/object&gt;
@@ -837,8 +842,11 @@ void Send(MessageQueue messageQueue, Message message);</programlisting>
<literal>Commit</literal> and <literal>Rollback</literal>. A specific
implementation is provided that will move the poison message to
another queue after a maximum number of redelivery attempts. See
<classname>SendToQueueExceptionHandler</classname> described
below.</para>
<classname>SendToQueueExceptionHandler</classname> described below.
You can set a specific implementation to by setting
<classname>TransactionalMessageListenerContainer's</classname>
property
<classname>MessageTransactionExceptionHandler</classname></para>
<para>The <literal>IMessageTransactionExceptionHandler</literal>
implementation <classname>SendToQueueExceptionHandler</classname>
@@ -946,9 +954,29 @@ void Send(MessageQueue messageQueue, Message message);</programlisting>
</itemizedlist>
<para>The default implementation used in
<classname>MessageQueueTemplate</classname> and the message listener is
an instance of XmlMessageConverter configured with a TargetType to be
System.String.</para>
<classname>MessageQueueTemplate</classname> and the message listener
containers is an instance of XmlMessageConverter configured with a
TargetType to be System.String. You specify the types that the
XmlMessageConverter can convert though either the array property
<classname>TargetTypes</classname> or
<classname>TargetTypeNames</classname>. Here is an example taken from
the QuickStart application</para>
<programlisting> &lt;object id="xmlMessageConverter" type="Spring.Messaging.Support.Converters.XmlMessageConverter, Spring.Messaging"&gt;
&lt;property name="TargetTypes"&gt;
&lt;list&gt;
&lt;value&gt;Spring.MsmqQuickStart.Common.Data.TradeRequest, Spring.MsmqQuickStart.Common&lt;/value&gt;
&lt;value&gt;Spring.MsmqQuickStart.Common.Data.TradeResponse, Spring.MsmqQuickStart.Common&lt;/value&gt;
&lt;value&gt;System.String, mscorlib&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/object&gt;</programlisting>
<para>You can specify other <classname>IMessageConverter</classname>
implementations using the
<classname>MessageConverterObjectName</classname> property on the
<classname>MessageQueueTemplate</classname> and
<classname>MessageListenerAdapter</classname>. </para>
<para>Other implementations provided are</para>
@@ -988,7 +1016,7 @@ void Send(MessageQueue messageQueue, Message message);</programlisting>
</section>
<section>
<title>interface based message processing</title>
<title>Interface based message processing</title>
<section>
<section>
@@ -1077,12 +1105,12 @@ void Send(MessageQueue messageQueue, Message message);</programlisting>
}</programlisting>
<para>The following configuration shows how to hook up the adapter to
process incoming MSMQ messages.</para>
process incoming MSMQ messages using the default message converter.
</para>
<programlisting> <emphasis role="bold">&lt;!-- Delegate to plain .NET object for message handling --&gt;</emphasis>
&lt;object id="messageListenerAdapter" type="Spring.Messaging.Listener.MessageListenerAdapter, Spring.Messaging"&gt;
&lt;property name="DefaultResponseQueueName" value="msmqTestResponseQueue"/&gt;
&lt;property name="MessageConverterObjectName" value="messageConverter"/&gt;
&lt;property name="HandlerObject" ref="myHandler"/&gt;
&lt;/object&gt;</programlisting>
</section>

View File

@@ -25,6 +25,9 @@
<imagedata fileref="images/nms-quickstart.jpg" scale="75" />
</imageobject>
</mediaobject>
<para>This example was developed with ActiveMQ 5.1 and the ActiveMQ NMS
library with subversion repository number 685750.</para>
</section>
<section>
@@ -55,7 +58,7 @@
<para>Queues are shown in red and topics in green.</para>
</section>
<section>
<section id="nms-gateways">
<title>Gateways</title>
<para>Gateways represent the service operation to send a message. The
@@ -89,7 +92,7 @@
purposes.</para>
</section>
<section>
<section id="nms-messagedata">
<title>Message Data</title>
<para>The <classname>TradeRequest</classname> object shown above contains
@@ -209,7 +212,7 @@
structure.</para>
</section>
<section>
<section id="nms-handlers">
<title>Message Handlers</title>
<para>When the <classname>TradeRequest</classname> message is received by
@@ -322,7 +325,7 @@
<para>The implementations of the gateway interfaces inherit from Spring's
helper class <classname>NmsGatewaySupport</classname> in order to get easy
access to a NmsTemplate for sending. The implementation of the
IStockService interface is shown below</para>
<classname>IStockService</classname> interface is shown below</para>
<programlisting> public class NmsStockServiceGateway : NmsGatewaySupport, IStockService
{
@@ -344,8 +347,14 @@
}
}</programlisting>
<para>The use of an anonymous delegate allows makes it very easy to apply
any post processing logic to the converted message. </para>
<para>The <classname>Send</classname> method is using NmsTemplate's
<literal>ConvertAndSendWithDelegate(object obj,
MessagePostProcessorDelegate messagePostProcessorDelegate)</literal>
method. The anonymous delegate allows you to modify the message
properties, such as NMSReplyTo and NMSCorrelationID after the message has
been converted from an object but before it has been sent. The use of an
anonymous delegate allows makes it very easy to apply any post processing
logic to the converted message.</para>
<para>The object definition for the
<classname>NmsStockServiceGateway</classname> is shown below along with
@@ -380,11 +389,11 @@
<para>A similar configuration is used on the server to configure the class
<classname>Spring.NmsQuickStart.Server.Gateways.MarketDataServiceGateway
</classname>that implements the <classname>IMarketDataService</classname>
interface. </para>
interface.</para>
<para>Since the client is also a consumer of messages, on the topic
APP.STOCK.MARKETDATA and the queue APP.STOCK.JOE (for Trader Joe!), two
message listener containers are defined as shown below. </para>
message listener containers are defined as shown below.</para>
<programlisting> &lt;nms:listener-container connection-factory="ConnectionFactory"&gt;
&lt;nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.JOE" /&gt;