[Springnet-commits] Spring.Net/doc/reference/src objects.xml, 1.122, 1.123
Brought to you by:
aseovic,
markpollack
From: Mark P. <mar...@us...> - 2008-04-21 19:34:42
|
Update of /cvsroot/springnet/Spring.Net/doc/reference/src In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv29447 Modified Files: objects.xml Log Message: update method injection docs Index: objects.xml =================================================================== RCS file: /cvsroot/springnet/Spring.Net/doc/reference/src/objects.xml,v retrieving revision 1.122 retrieving revision 1.123 diff -C2 -d -r1.122 -r1.123 *** objects.xml 3 Apr 2008 02:17:46 -0000 1.122 --- objects.xml 21 Apr 2008 19:34:32 -0000 1.123 *************** *** 112,136 **** Spring Java framework.</para> </note> - </sect3> ! <para>Spring configuration consists of at least one object definition ! that the container must manage, but typically there will be more than ! one object definition. When using XML-based configuration metadata, ! these object are configured as <object/> elements inside a ! top-level <objects/> element.</para> ! <para>These object definitions correspond to the actual objects that ! make up your application. Typically you will have object definitions for ! your service layer objects, your data access objects (DAOs), ! presentation objects such as ASP.NET page instances, infrastructure ! objects such as NHibernate SessionFactories, and so forth. Typically one ! does not configure fine-grained domain objects in the container, because ! it is usually the responsibility of DAOs and business logic to ! create/load domain objects.</para> ! <para>Find below an example of the basic structure of XML-based ! configuration metadata.</para> ! <programlisting><objects xmlns="http://www.springframework.net"> <object id="..." type="..."> --- 112,135 ---- Spring Java framework.</para> </note> ! <para>Spring configuration consists of at least one object definition ! that the container must manage, but typically there will be more than ! one object definition. When using XML-based configuration metadata, ! these object are configured as <object/> elements inside a ! top-level <objects/> element.</para> ! <para>These object definitions correspond to the actual objects that ! make up your application. Typically you will have object definitions ! for your service layer objects, your data access objects (DAOs), ! presentation objects such as ASP.NET page instances, infrastructure ! objects such as NHibernate SessionFactories, and so forth. Typically ! one does not configure fine-grained domain objects in the container, ! because it is usually the responsibility of DAOs and business logic to ! create/load domain objects.</para> ! <para>Find below an example of the basic structure of XML-based ! configuration metadata.</para> ! <programlisting><objects xmlns="http://www.springframework.net"> <object id="..." type="..."> *************** *** 145,155 **** </objects></programlisting> ! <sect3 id="objects-create-container"> ! <title>Instantiating a container</title> ! <para>Instantiating a Spring IoC container is straightforward.</para> ! <programlisting>IApplicationContext context = new XmlApplicationContext( "file://services.xml", "assembly://MyAssembly/MyDataAccess/data-access.xml"); --- 144,156 ---- </objects></programlisting> + </sect3> + </sect2> ! <sect2 id="objects-factory-instantiation"> ! <title>Instantiating a container</title> ! <para>Instantiating a Spring IoC container is straightforward.</para> ! <programlisting>IApplicationContext context = new XmlApplicationContext( "file://services.xml", "assembly://MyAssembly/MyDataAccess/data-access.xml"); *************** *** 158,175 **** IObjectFactory factory = context;</programlisting> ! <para>You can also create an container by using a custom configuration ! section in the standard .NET application (or web) configuration file. ! Once the container has been created you may never need to explicitly ! interact with it again in your code, for example when configuring ! ASP.NET pages.</para> ! </sect3> <para>You may be wondering what the assembly URL is all about. The above ! example uses Spring.NET's <classname> ! <ulink ! url="http://www.springframework.net/doc/api/html/Spring.Core.IO.IResource.html">IResource</ulink> ! </classname> abstraction. The <classname>IResource</classname> ! interface provides a simple and uniform interface to a wide array of IO ! resources that can represent themselves as <classname>System.IO.Stream</classname>. An example for a file based resource, not using the URL syntax but an implementation of the --- 159,174 ---- IObjectFactory factory = context;</programlisting> ! <para>You can also create an container by using a custom configuration ! section in the standard .NET application (or web) configuration file. ! Once the container has been created you may never need to explicitly ! interact with it again in your code, for example when configuring ! ASP.NET pages.</para> <para>You may be wondering what the assembly URL is all about. The above ! example uses Spring.NET's <classname> <ulink ! url="http://www.springframework.net/doc/api/html/Spring.Core.IO.IResource.html">IResource</ulink> ! </classname> abstraction. The <classname>IResource</classname> interface ! provides a simple and uniform interface to a wide array of IO resources ! that can represent themselves as <classname>System.IO.Stream</classname>. An example for a file based resource, not using the URL syntax but an implementation of the *************** *** 188,200 **** referring to a resource that has been embedded inside a .NET assembly, <literal>assembly://<AssemblyName>/<NameSpace>/<ResourceName> ! </literal> <note> To create an embedded resource using Visual Studio you ! must set the Build Action of the .xml configuration file to Embedded ! Resource in the file property editor. Also, you will need to explicitly ! rebuild the project containing the configuration file if it is the only ! change you make between successive builds. If using NAnt to build, add a ! <resources> section to the csc task. For example usage, look at ! the Spring.Core.Tests.build file included the distribution. </note> The ! <classname>IResource</classname> abstraction is explained further in ! <xref linkend="objects-iresource" />.</para> <para>The preferred way to create an --- 187,194 ---- referring to a resource that has been embedded inside a .NET assembly, <literal>assembly://<AssemblyName>/<NameSpace>/<ResourceName> ! </literal> <note> ! To create an embedded resource using Visual Studio you must set the Build Action of the .xml configuration file to Embedded Resource in the file property editor. Also, you will need to explicitly rebuild the project containing the configuration file if it is the only change you make between successive builds. If using NAnt to build, add a <resources> section to the csc task. For example usage, look at the Spring.Core.Tests.build file included the distribution. ! </note> The <classname>IResource</classname> abstraction is explained ! further in <xref linkend="objects-iresource" />.</para> <para>The preferred way to create an *************** *** 307,311 **** section <xref linkend="context-configuration" /></para> ! <sect3> <title>Composing XML-based configuration metadata</title> --- 301,305 ---- section <xref linkend="context-configuration" /></para> ! <sect3 id="objects-factoyr-xml-import"> <title>Composing XML-based configuration metadata</title> *************** *** 327,332 **** Let's look at a sample:</para> ! <para> ! <programlisting><objects xmlns="http://www.springframework.net"> <import resource="services.xml"/> --- 321,325 ---- Let's look at a sample:</para> ! <para><programlisting><objects xmlns="http://www.springframework.net"> <import resource="services.xml"/> *************** *** 337,342 **** <object id="object2" type="..."/> ! </objects></programlisting> ! </para> <para>In this example, external object definitions are being loaded --- 330,334 ---- <object id="object2" type="..."/> ! </objects></programlisting></para> <para>In this example, external object definitions are being loaded *************** *** 868,871 **** --- 860,888 ---- </sect3> </sect2> + + <sect2 id="objects-factory-client"> + <title>Using the container</title> + + <para>An <classname>IApplicationContext</classname> is essentially + nothing more than the interface for an advanced factory capable of + maintaining a registry of different objects and their dependencies. The + <classname>IApplicationContext</classname> enables you to read object + definitions and access them. You create one and read in some object + definition in the XML format as follows:</para> + + <programlisting>IApplicationContext context = new XmlApplicationContext("file://objects.xml"); + </programlisting> + + <para>Basically that is all there is to it. Using + <literal>GetObject(string)</literal> or the indexer + <literal>[string]</literal>, you can retrieve instances of your object; + the client-side view of the <classname>IApplicationContext</classname> + is simple. The <classname>IApplicationContext</classname> interface has + just a few other methods related to finding objects in the contianer, + but ideally your application code should never use them... indeed, your + application code should have no calls to the + <literal>GetObject(string)</literal> method at all, and thus no + dependency on Spring APIs at all.</para> + </sect2> </sect1> *************** *** 2393,2407 **** <para>One solution to this problem is to forego some inversion of ! control. Object A can be aware of the container by implementing the ! <classname>IObjectFactoryAware</classname> interface, and use ! programmatic means to ask the container via a ! <literal>GetObject("B")</literal> call for (a new) object B every time ! it needs it. This is generally not a desirable solution since the object ! code is then aware of and coupled to Spring.NET.</para> ! <para>Method Injection, an advanced feature of supporting ! <classname>IObjectFactoryAware</classname> implementations, allows this ! use case to be handled in a clean fashion, along with some other ! scenarios.</para> <sect3 id="objects-method-injection-lookup"> --- 2410,2457 ---- <para>One solution to this problem is to forego some inversion of ! control. Object A can be <link lang="" ! linkend="objects-factory-aware-objectfactoryaware">made aware of the ! container</link> by implementing the ! <classname>IObjectFactoryAware</classname> interface, and <link ! linkend="objects-factory-client">use programmatic means</link> to ask ! the container via a <literal>GetObject("B")</literal> call for (a ! typically new) object B every time it needs it. Find below an admittedly ! somewhat contrived example of this approach</para> ! <programlisting>using System.Collections; ! using Spring.Objects.Factory; ! ! namespace Fiona.Apple ! { ! public class CommandManager : IObjectFactoryAware ! { ! private IObjectFactory objectFactory; ! ! public object Process(IDictionary commandState) ! { ! // grab a new instance of the appropriate Command ! Command command = CreateCommand(); ! // set the state on the (hopefully brand new) Command instance ! command.State = commandState; ! return command.Execute(); ! } ! ! // the Command returned here could be an implementation that executes asynchronously, or whatever ! protected Command CreateCommand() ! { ! return (Command) objectFactory.GetObject("command"); // notice the Spring API dependency ! } ! ! public IObjectFactory ObjectFactory ! { ! set { objectFactory = value; } ! } ! } ! }</programlisting> ! ! <para>The above example is generally not a desirable solution since the ! business code is then aware of and coupled to the Spring Framework. ! Method Injection, a somewhat advanced feature of the Spring IoC ! container, allows this use case to be handled in a clean fashion.</para> <sect3 id="objects-method-injection-lookup"> *************** *** 2409,2451 **** <para>Lookup method injection refers to the ability of the container ! to override <literal>abstract</literal> or concrete methods on managed ! objects in the container, and to return the result of looking up ! another named object in the container. The lookup will typically be of ! a non-singleton object as per the scenario described above (although ! it can also be a singleton). Spring.NET implements this through a ! dynamically generated subclass overriding the method using the classes ! in the <literal>System.Reflection.Emit</literal> namespace.</para> ! <para>In the client class containing the method to be injected, the ! method definition must observe the following form:</para> ! <programlisting>protected abstract SingleShotHelper CreateSingleShotHelper();</programlisting> ! <para>If the method is not <literal>abstract</literal>, Spring.NET ! will simply override the existing implementation. In the ! <classname>XmlObjectFactory</classname> case, you instruct Spring.NET ! to inject / override this method to return a particular object from ! the container, by using the <literal>lookup-method</literal> element ! inside the object definition. For example:</para> <programlisting><!-- a stateful object deployed as a prototype (non-singleton) --> ! <object id="singleShotHelper" class="..." singleton="false"/> ! <!-- myobject uses singleShotHelper --> ! <object id="myObject" type="..."> ! <lookup-method name="CreateSingleShotHelper" object="singleShotHelper"/> ! <property> ! ... ! </property> </object></programlisting> ! <para>The object identified as <literal>myObject</literal> will call ! its own method <literal>CreateSingleShotHelper</literal> whenever it ! needs a new instance of the <literal>singleShotHelper</literal> ! object. It is important to note that the person deploying the objects ! must be careful to deploy the <literal>singleShotHelper</literal> ! object as a non-singleton (if that is actually what is needed). If it ! is deployed as a singleton (either explicitly, or relying on the ! default <literal>true</literal> setting for this flag), the same instance of <literal>singleShotHelper</literal> will be returned each time!</para> --- 2459,2528 ---- <para>Lookup method injection refers to the ability of the container ! to override <literal>abstract</literal> or concrete methods on ! <emphasis>container managed objects</emphasis>, to return the result ! of looking up another named object in the container. The lookup will ! typically be of a prototype object as in the scenario described above. ! The Spring framework implements this method injection by a dynamically ! generating a subclass overriding the method using the classes in the ! <literal>System.Reflection.Emit</literal> namespace. You can read more ! about the motivation for Method Injection in <ulink ! url="http://blog.springframework.com/rod/?p=1">this blog ! entry</ulink>.</para> ! <para>So if you look at the code from the previous code snipped (the ! <literal>CommandManager</literal> class), the Spring container is ! going to dynamically override the implementation of the ! <literal>CreateCommand()</literal> method. Your ! <classname>CommandManager</classname> class is not going to have any ! Spring dependencies, as can be seen in this reworked example ! below:</para> ! <programlisting>using System.Collections; ! namespace Fiona.Apple ! { ! public abstract class CommandManager ! { ! ! public object Process(IDictionary commandState) ! { ! Command command = CreateCommand(); ! command.State = commandState; ! return command.Execute(); ! } ! ! // okay... but where is the implementation of this method? ! protected abstract Command CreateCommand(); ! } ! }</programlisting> ! ! <para>In the client class containing the method to be injected (the ! CommandManager in this case) the method definition must observe the ! following form:</para> ! ! <programlisting><public|protected> [abstract] <return-type> TheMethodName(no-arguments);</programlisting> ! ! <para>If the method is <literal>abstract</literal>, the ! dynamically-generated subclass will implement the method. Otherwise, ! the dynamically-generated subclass will override the concrete method ! defined in the original class. Let's look at an example:</para> <programlisting><!-- a stateful object deployed as a prototype (non-singleton) --> ! <object id="command" class="Fiona.Apple.AsyncCommand, Fiona" singleton="false"> ! <!-- inject dependencies here as required --> ! </object> ! <!-- commandProcessor uses a statefulCommandHelpder --> ! <object id="commandManager" type="Fiona.Apple.CommandManager, Fiona"> ! <lookup-method name="CreateCommand" object="command"/> </object></programlisting> ! <para>The object identified as <literal>commandManager</literal> will ! call its own method <literal>CreateCommand</literal> whenever it needs ! a new instance of the <literal>command</literal> object. It is ! important to note that the person deploying the objects must be ! careful to deploy the <literal>command</literal> object as prototype ! (if that is actually what is needed). If it is deployed as a <link ! linkend="objects-factory-scopes-singleton">singleton</link> the same instance of <literal>singleShotHelper</literal> will be returned each time!</para> *************** *** 2501,2507 **** }</programlisting> ! <para>The attendant <classname>IObjectFactory</classname> definition ! to deploy the original class and specify the method override would ! look like:</para> <programlisting><object id="myValueCalculator" type="Examples.MyValueCalculator, ExampleAssembly"> --- 2578,2583 ---- }</programlisting> ! <para>The object definition to deploy the original class and specify ! the method override would look like this:</para> <programlisting><object id="myValueCalculator" type="Examples.MyValueCalculator, ExampleAssembly"> *************** *** 2990,2994 **** </table> ! <sect2> <title>The singleton scope</title> --- 3066,3070 ---- </table> ! <sect2 id="objects-factory-scopes-singleton"> <title>The singleton scope</title> *************** *** 3025,3029 **** </sect2> ! <sect2> <title>The prototype scope</title> --- 3101,3105 ---- </sect2> ! <sect2 id="objects-factory-scopes-prototype"> <title>The prototype scope</title> *************** *** 3066,3070 **** </sect2> ! <sect2> <title>Singleton objecgts with prototype-object dependencies</title> --- 3142,3146 ---- </sect2> ! <sect2 id="objects-factory-scopes-sing-prot-interaction"> <title>Singleton objecgts with prototype-object dependencies</title> *************** *** 4180,4184 **** organization / team) have defined an attribute called [Mandatory]. You can make a <classname>RequiredAttributeObjectPostProcessor</classname> ! instance <literal>[Mandatory]</literal>-aware like so: </para> <programlisting><object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"> --- 4256,4260 ---- organization / team) have defined an attribute called [Mandatory]. You can make a <classname>RequiredAttributeObjectPostProcessor</classname> ! instance <literal>[Mandatory]</literal>-aware like so:</para> <programlisting><object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"> *************** *** 4674,4679 **** object from an embedded resource file and use it to set another objects dependency. An example of this is provided <ulink ! url="http://jira.springframework.org/browse/SPRNET-133#action_19743">here</ulink>. ! </para> <para>Finally, there is sometimes a need to ask a container for an --- 4750,4754 ---- object from an embedded resource file and use it to set another objects dependency. An example of this is provided <ulink ! url="http://jira.springframework.org/browse/SPRNET-133#action_19743">here</ulink>.</para> <para>Finally, there is sometimes a need to ask a container for an |