5840 lines
277 KiB
XML
5840 lines
277 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<chapter id="objects">
|
|
<title>The IoC container</title>
|
|
|
|
<sect1 id="objects-introduction">
|
|
<title>Introduction</title>
|
|
|
|
<para>This chapter covers the Spring Framework's implementation of the
|
|
Inversion of Control (IoC) <footnote>
|
|
<para>See the section entitled <xref
|
|
linkend="background-ioc" /></para>
|
|
</footnote> principle</para>
|
|
|
|
<para>The <literal>Spring.Core</literal> assembly provides the basis for
|
|
the Spring.NET Inversion of Control container. The <classname><ulink
|
|
url="http://www.springframework.net/doc/api/html/Spring.Objects.Factory.IObjectFactory.html">IObjectFactory</ulink></classname>
|
|
interface provides an advanced configuration mechanism capable of managing
|
|
objects of any nature. The <classname><ulink
|
|
url="http://www.springframework.net/doc/api/html/Spring.Context.IApplicationContext.html">IApplicationContext</ulink></classname>
|
|
interface builds on top of the <classname>IObjectFactory</classname> (it
|
|
is a sub-interface) and adds other functionality such as easier
|
|
integration with Spring.NET's Aspect Oriented Programming (AOP) features,
|
|
message resource handling (for use in internationalization), event
|
|
propagation and application layer-specific context such as
|
|
<classname>WebApplicationContext</classname> for use in web
|
|
applications.</para>
|
|
|
|
<para>In short, the <classname>IObjectFactory</classname> provides the
|
|
configuration framework and basic functionality, while the
|
|
<classname>IApplicationContext</classname> adds more enterprise-centric
|
|
functionality to it. The <classname>IApplicationContext</classname> is a
|
|
complete superset of the <classname>IObjectFactory</classname>, and any
|
|
description of <classname>IObjectFactory</classname> capabilities and
|
|
behavior should be considered to apply to
|
|
<literal>IApplicationContext</literal>s as well.</para>
|
|
|
|
<para>This chapter is divided into two parts, with the <link
|
|
linkend="objects-basics">first part</link> covering the basic principles
|
|
that apply to both the <classname>IObjectFactory</classname> and
|
|
<classname>IApplicationContext</classname>, with the <link
|
|
linkend="context-introduction">second part</link> covering those features
|
|
that apply only to the <classname>IApplicationContext</classname>
|
|
interface.</para>
|
|
|
|
<para>If you are new to Spring.NET or IoC containers in general, you may
|
|
want to consider starting with <xref linkend="quickstarts" />, which
|
|
contains a number of introductory level examples that actually demonstrate
|
|
a lot of what is described in detail below. Don't worry if you don't
|
|
absorb everything at once... those examples serve only to paint a picture
|
|
of how Spring.NET hangs together in really broad brushstrokes. Once you
|
|
have finished with those examples, you can come back to this section which
|
|
will fill in all the fine detail.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="objects-basics">
|
|
<title>Basics - containers and objects</title>
|
|
|
|
<sect2 id="objects-factory">
|
|
<title>The container</title>
|
|
|
|
<para>The <classname>IObjectFactory</classname> is the actual
|
|
representation of the Spring IoC container that is responsible for
|
|
instantiating, configuring, and managing a number of objects.</para>
|
|
|
|
<para>The <literal>IObjectFactory</literal> interface is the central IoC
|
|
container interface in Spring. Its responsibilities include
|
|
instantiating or sourcing application objects, configuring such objects,
|
|
and assembling the dependencies between these objects.</para>
|
|
|
|
<para>There are a number of implementations of the
|
|
<classname>IObjectFactory</classname> interface that come supplied
|
|
straight out-of-the-box with Spring. The most commonly used
|
|
<classname>IObjectFactory</classname> implementation is the
|
|
<classname>XmlObjectFactory</classname> class. This implementation
|
|
allows you to express the objects that compose your application, and the
|
|
doubtless rich interdependencies between such objects, in terms of XML.
|
|
The <classname>XmlObjectFactory</classname> takes this XML configuration
|
|
metadata and uses it to create a fully configured system or application.
|
|
Interaction with the <classname>IObjectFactory</classname> interface is
|
|
discussed in <xref linkend="objects-factory-client" />. Additional
|
|
features offered by another implementation of
|
|
<classname>IObjectFactory</classname>, the
|
|
<classname>IApplicationContext</classname>, are discussed in section
|
|
<xref linkend="context-introduction" />.</para>
|
|
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata fileref="images/container-in-action.gif" format="GIF" />
|
|
</imageobject>
|
|
</mediaobject>
|
|
|
|
<sect3 id="objects-configuration-metadata">
|
|
<title>Configuration metadata</title>
|
|
|
|
<para>As can be seen in the above image, the Spring IoC container
|
|
consumes some form of configuration metadata; this configuration
|
|
metadata is nothing more than how you (as an application developer)
|
|
inform the Spring container as to how to “instantiate, configure, and
|
|
assemble [the objects in your application]”. This configuration
|
|
metadata is typically supplied in a simple and intuitive XML format.
|
|
When using XML-based configuration metadata, you write object
|
|
definitions for those object that you want the Spring IoC container to
|
|
manage, and then let the container do it's stuff.</para>
|
|
|
|
<note>
|
|
<para>XML-based metadata is by far the most commonly used form of
|
|
configuration metadata. It is not however the only form of
|
|
configuration metadata that is allowed. The Spring IoC container
|
|
itself is totally decoupled from the format in which this
|
|
configuration metadata is actually written. Attribute based metadata
|
|
will be part of an upcoming release and it is already part of the
|
|
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 language="myxml"><objects xmlns="http://www.springframework.net">
|
|
|
|
<object id="..." type="...">
|
|
<!-- collaborators and configuration for this object go here -->
|
|
</object>
|
|
|
|
<object id="...." type="...">
|
|
<!-- collaborators and configuration for this object go here -->
|
|
</object>
|
|
|
|
<!-- more object definitions go here -->
|
|
|
|
</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");
|
|
|
|
// an IApplicationContext is also an IObjectFactory (via inheritance)
|
|
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
|
|
IResource interface for file is shown below.<programlisting>[C#]
|
|
IResource input = new FileSystemResource ("objects.xml");
|
|
IObjectFactory factory = new XmlObjectFactory(input);</programlisting></para>
|
|
|
|
<para>These resources are most frequently files or URLs but can also be
|
|
resources that have been embedded inside a .NET assembly. A simple URI
|
|
syntax is used to describe the location of the resource, which follows
|
|
the standard conventions for files, i.e.
|
|
<literal>file://object.xml</literal> and other well known protocols such
|
|
as http.</para>
|
|
|
|
<para>The following snippet shows the use of the URI syntax for
|
|
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
|
|
<classname>IApplicationContext</classname> or
|
|
<classname>IObjectFactory</classname> is to use a custom configuration
|
|
section in the standard .NET application configuration file (one of
|
|
<literal>App.config</literal> or <literal>Web.config</literal>). A
|
|
custom configuration section that creates the same
|
|
<classname>IApplicationContext</classname> as the previous example is
|
|
<programlisting><spring>
|
|
<context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
|
|
<resource uri="file://services.xml"/>
|
|
<resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/>
|
|
</context>
|
|
</spring></programlisting> The context type (specified as the value of
|
|
the <literal>type</literal> attribute of the <literal>context</literal>
|
|
element) is wholly optional, and defaults to the
|
|
<classname>Spring.Context.Support.XmlApplicationContext</classname>
|
|
class, so the following XML snippet is functionally equivalent to the
|
|
first. <programlisting><spring>
|
|
<context>
|
|
<resource uri="file://services.xml"/>
|
|
<resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/>
|
|
</context>
|
|
</spring> </programlisting></para>
|
|
|
|
<para>To acquire a reference to an
|
|
<classname>IApplicationContext</classname> using a custom configuration
|
|
section, one simply uses the following code; <programlisting>IApplicationContext ctx = ContextRegistry.GetContext();</programlisting>
|
|
The <classname>ContextRegistry</classname> is used to both instantiate
|
|
the application context and to perform service locator style access to
|
|
other objects. (See <xref linkend="objects-servicelocator" /> for more
|
|
information). The glue that makes this possible is an implementation of
|
|
the Base Class Library (BCL) provided
|
|
<classname>IConfigurationSectionHandler</classname> interface, namely
|
|
the <classname>Spring.Context.Support.ContextHandler</classname> class.
|
|
The handler class needs to be registered in the
|
|
<literal>configSections</literal> section of the .NET configuration file
|
|
as shown below. <programlisting><configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
</configSections> </programlisting> This declaration now enables the use
|
|
of a custom context section starting at the <literal>spring</literal>
|
|
root element.</para>
|
|
|
|
<para>In some usage scenarios, user code will not have to explicitly
|
|
instantiate an appropriate implementation of the
|
|
<classname>IObjectFactory</classname> interface, since Spring.NET code
|
|
will do it. For example, the ASP.NET web layer provides support code to
|
|
load a Spring.NET <classname>IApplicationContext</classname>
|
|
automatically as part of the normal startup process of an ASP.NET web
|
|
application. Similar support for WinForms applications is being
|
|
investigated.</para>
|
|
|
|
<para>While programmatic manipulation of
|
|
<literal>IObjectFactory</literal> instances will be described later, the
|
|
following sections will concentrate on describing the configuration of
|
|
objects managed by <literal>IObjectFactory</literal> instances.</para>
|
|
|
|
<para>Spring.NET comes with an XSD schema to make the validation of the
|
|
XML object definitions a whole lot easier. The XSD document is
|
|
thoroughly documented so feel free to take a peek inside (see <xref
|
|
linkend="springobjectsxsd" />). The XSD is currently used in the
|
|
implementation code to validate the XML document. The XSD schema serves
|
|
a dual purpose in that it also facilitates the editing of XML object
|
|
definitions inside an XSD aware editor (typically Visual Studio) by
|
|
providing validation (and Intellisense support in the case of Visual
|
|
Studio). You may wish to refer to <xref linkend="vsnet" /> for more
|
|
information regarding such integration.</para>
|
|
|
|
<para>Your XML object definitions can also be defined within the
|
|
standard .NET application configuration file by registering the
|
|
<classname>Spring.Context.Support.DefaultSectionHandler</classname>
|
|
class as the configuration section handler for inline object
|
|
definitions. This allows you to completely configure one or more
|
|
<classname>IApplicationContext</classname> instances within a single
|
|
standard .NET application configuration file as shown in the following
|
|
example. <programlisting><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
|
|
<context>
|
|
<resource uri="config://spring/objects"/>
|
|
</context>
|
|
|
|
<objects xmlns="http://www.springframework.net">
|
|
...
|
|
</objects>
|
|
|
|
</spring>
|
|
|
|
</configuration></programlisting></para>
|
|
|
|
<para>Other options available to structure the configuration files are
|
|
described in <xref linkend="context-functionality-hierarchy" /> and
|
|
<xref linkend="context-import" />.</para>
|
|
|
|
<para>The <classname>IApplicationContext</classname> can be configured
|
|
to register other resource handlers, custom parsers to integrate
|
|
user-contributed XML schema into the object definitions section, type
|
|
converters, and define type aliases. These features are discussed in
|
|
section <xref linkend="context-configuration" /></para>
|
|
|
|
<sect3 id="objects-factoyr-xml-import">
|
|
<title>Composing XML-based configuration metadata</title>
|
|
|
|
<para>It is often useful to split up container definitions into
|
|
multiple XML files. One way to then load an application context which
|
|
is configured from all these XML fragments is to use the application
|
|
context constructor which takes multiple resource locations. With an
|
|
object factory, an object definition reader can be used multiple times
|
|
to read definitions from each file in turn.</para>
|
|
|
|
<para>Generally, the Spring.NET team prefers the above approach,
|
|
assembling individual files because it keeps container configuration
|
|
files unaware of the fact that they are being combined with others.
|
|
However, an alternate approach is to compose one XML object definition
|
|
file using one or more occurrences of the <literal>import</literal>
|
|
element to load definitions from other files. Any
|
|
<literal>import</literal> elements must be placed before
|
|
<literal>object</literal> elements in the file doing the importing.
|
|
Let's look at a sample:</para>
|
|
|
|
<para><programlisting><objects xmlns="http://www.springframework.net">
|
|
|
|
<import resource="services.xml"/>
|
|
<import resource="resources/messageSource.xml"/>
|
|
<import resource="/resources/themeSource.xml"/>
|
|
|
|
<object id="object1" type="..."/>
|
|
<object id="object2" type="..."/>
|
|
|
|
</objects></programlisting></para>
|
|
|
|
<para>In this example, external object definitions are being loaded
|
|
from 3 files, <literal>services.xml</literal>,
|
|
<literal>messageSource.xml</literal>, and
|
|
<literal>themeSource.xml</literal>. All location paths are considered
|
|
relative to the definition file doing the importing, so
|
|
<literal>services.xml</literal> in this case must be in the same
|
|
directory as the file doing the importing, while
|
|
<literal>messageSource.xml</literal> and
|
|
<literal>themeSource.xml</literal> must be in a
|
|
<literal>resources</literal> location below the location of the
|
|
importing file. As you can see, a leading slash is actually ignored,
|
|
but given that these are considered relative paths, it is probably
|
|
better form not to use the slash at all. The contents of the files
|
|
being imported must be fully valid XML object definition files
|
|
according to the XSD, including the top level
|
|
<literal>objects</literal> element.</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-definition">
|
|
<title>The Objects</title>
|
|
|
|
<para>A Spring IoC container manages one or more objects. these objects
|
|
are created using the configuration metadata that has been supplied to
|
|
the container (typically in the form of XML <object/>
|
|
definitions).</para>
|
|
|
|
<para>Within the container itself, these object definitions are
|
|
represented as IObjectDefinition objects, which contain (among other
|
|
information) the following metadata: <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><emphasis>A type name</emphasis>: typically this is the
|
|
actual implementation class of the object being defined..</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Object behavioral configuration elements, which state how
|
|
the object should behave in the Spring.NET IoC container (i.e.
|
|
prototype or singleton, lifecycle callbacks, and so forth)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>references to other objects which are needed for the object
|
|
to do its work: these references are also called
|
|
<emphasis>collaborators</emphasis> or
|
|
<emphasis>dependencies</emphasis>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>other configuration settings to set in the newly created
|
|
object. An example would be the number of threads to use in an
|
|
object that manages a worker thread pool, or the size limit of the
|
|
pool.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>The concepts listed above directly translate to a set of elements
|
|
the object definition consists of. These elements are listed below,
|
|
along with a link to further documentation about each of them. <table
|
|
frame="all">
|
|
<title>Object definition explanation</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="2*" />
|
|
|
|
<colspec colname="c2" colwidth="4*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Feature</entry>
|
|
|
|
<entry>More info</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>type</entry>
|
|
|
|
<entry><xref linkend="objects-factory-class" /></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>id and name</entry>
|
|
|
|
<entry><xref linkend="objects-objectname" /></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>singleton or prototype</entry>
|
|
|
|
<entry><xref linkend="objects-factory-modes" /></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>object properties</entry>
|
|
|
|
<entry><xref
|
|
linkend="objects-factory-collaborators" /></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>constructor arguments</entry>
|
|
|
|
<entry><xref
|
|
linkend="objects-factory-collaborators" /></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>autowiring mode</entry>
|
|
|
|
<entry><xref linkend="objects-factory-autowire" /></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>dependency checking mode</entry>
|
|
|
|
<entry><xref linkend="objects-factory-dependencies" /></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>initialization method</entry>
|
|
|
|
<entry><xref linkend="objects-factory-lifecycle" /></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>destruction method</entry>
|
|
|
|
<entry><xref linkend="objects-factory-lifecycle" /></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
|
|
<para>Besides object definitions which contain information on how to
|
|
create a specific object, certain <classname>IObjectFactory</classname>
|
|
implementations also permit the registration of existing objects that
|
|
have been created outside the factory (by user code). The
|
|
<classname>DefaultListableObjectFactory</classname> class supports this
|
|
through the <literal>RegisterSingleton(..)</literal> method. (Typical
|
|
applications solely work with objects defined through metadata object
|
|
definitions though.)</para>
|
|
|
|
<sect3>
|
|
<title>Naming objects</title>
|
|
|
|
<para>Every object has one or more <literal>id</literal>s (also called
|
|
identifiers, or names; these terms refer to the same thing). These
|
|
<literal>id</literal>s must be unique within the container the object
|
|
is hosted in. An object will almost always have only one id, but if an
|
|
object has more than one id, the extra ones can essentially be
|
|
considered aliases.</para>
|
|
|
|
<para>When using XML-based configuration metadata, you use the
|
|
<literal>'id'</literal> or <literal>'name'</literal>attributes to
|
|
specify the object identifier(s). The <literal>'id'</literal>
|
|
attribute allows you to specify exactly one id, and as it is a real
|
|
XML element ID attribute, the XML parser is able to do some extra
|
|
validation when other elements reference the id; as such, it is the
|
|
preferred way to specify an object id. However, the XML specification
|
|
does limit the characters which are legal in XML IDs. This is usually
|
|
not a constraint, but if you have a need to use one of these special
|
|
XML characters, or want to introduce other aliases to the object, you
|
|
may also or instead specify one or more object <literal>id</literal>s,
|
|
separated by a comma (<literal>,</literal>), semicolon
|
|
(<literal>;</literal>), or whitespace in the <literal>'name'</literal>
|
|
attribute.</para>
|
|
|
|
<para>Please note that you are not required to supply a name for a
|
|
object. If no name is supplied explicitly, the container will generate
|
|
a unique name for that object. The motivations for not supplying a
|
|
name for a object will be discussed later (one use case is inner
|
|
objects).</para>
|
|
|
|
<sect4>
|
|
<title>Aliasing objects</title>
|
|
|
|
<para>In an object definition itself, you may supply more than one
|
|
name for the object, by using a combination of the id and name
|
|
attributes as discussed in <xref linkend="objects-objectname" />.
|
|
This approach to aliasing objects has some limitations when you
|
|
would like to assemble the main application configuration file from
|
|
multiple files. See <xref linkend="context-import" /> for more
|
|
information. This usage pattern is common when each configuration
|
|
file represents a logical layer or component within the application.
|
|
In this case you may want to refer to a common object dependency
|
|
using a name that is specific to each file. If the common object
|
|
dependency is defined in the main application configuration file
|
|
itself, then one can use the name element as an alias mechanism.
|
|
However, if the main application configuration file should not be
|
|
responsible for defining the common object dependency, since it
|
|
logically 'belongs' to one of the other layers or components, you
|
|
can not use the name attribute to achieve this goal.</para>
|
|
|
|
<para>In this case, you can define an alias using an explicit
|
|
<literal>alias</literal> element contained in the main application
|
|
configuration file.</para>
|
|
|
|
<para><literal> <alias name="fromName"
|
|
alias="toName"/></literal></para>
|
|
|
|
<para>This allows an object named <literal>fromName</literal> to be
|
|
referred to as <literal>toName</literal> across all application
|
|
configuration files.</para>
|
|
|
|
<para>As a concrete example, consider the case where the
|
|
configuration file 'a.xml' (representing component A) defines a
|
|
connection object called componentA-connection. In another file,
|
|
'b.xml' (representing component B) would like to refer to the
|
|
connection as componentB-connection. And the main application,
|
|
MyApp, defines its own XML fragment to assembles the final
|
|
application configuration from all three fragments and would like to
|
|
refer to the connection as myApp-connection. This scenario can be
|
|
easily handled by adding to the MyApp XML fragment the following
|
|
standalone aliases:</para>
|
|
|
|
<para><literal> </literal><literal><alias
|
|
name="componentA-connection"
|
|
alias="componentB-connection"/></literal></para>
|
|
|
|
<para><literal> <alias name="componentA-connection"
|
|
alias="myApp-connection"/></literal></para>
|
|
|
|
<para>Now each component and the main app can refer to the
|
|
connection via a name that is unique and guaranteed not to clash
|
|
with any other definition (effectively there is a namespace), yet
|
|
they refer to the same object.</para>
|
|
</sect4>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-factory-class">
|
|
<title>Object creation</title>
|
|
|
|
<para>An object definition essentially is a recipe for creating one or
|
|
more objects. The container looks at the recipe for a named object when
|
|
asked, and uses the configuration metadata encapsulated by that object
|
|
definition to create (or acquire) an actual object.</para>
|
|
|
|
<para>If you are using XML-based configuration metadata, you can specify
|
|
the type of object that is to be instantiated using the
|
|
<literal>'type'</literal> attribute of the
|
|
<literal><object/></literal> element. This
|
|
<literal>'type'</literal> attribute (which internally eventually boils
|
|
down to being a <literal>Type</literal> property on a
|
|
<literal>IObjectDefinition</literal> instance) is normally mandatory
|
|
(see XXX “Instantiation using an instance factory method” and XXX
|
|
“Object definition inheritance” for the two exceptions) and is used for
|
|
one of two purposes. The type property specifies the type of of the
|
|
object to be constructed in the common case where the container itself
|
|
directly creates the object by calling its constructor reflectively
|
|
(somewhat equivalent to C# code using the <emphasis>'new'
|
|
</emphasis>operator). In the less common case where the container
|
|
invokes a <literal>static</literal>, <emphasis>factory</emphasis> method
|
|
on a class to create the object, the type property specifies the actual
|
|
class containing the <literal>static</literal> factory method that is to
|
|
be invoked to create the object (the type of the object returned from
|
|
the invocation of the <literal>static</literal> factory method may be
|
|
the same type or another type entirely, it doesn't matter).</para>
|
|
|
|
<sect3 id="objects-factory-class-ctor">
|
|
<title>Object creation via constructor invocation</title>
|
|
|
|
<para>When creating an object using the constructor approach, all
|
|
normal classes are usable by and compatible with Spring. That is, the
|
|
type being created does not need to implement any specific interfaces
|
|
or be coded in a specific fashion. Just specifying the object type
|
|
should be enough. However, depending on what type of IoC you are going
|
|
to use for that specific object, you may need to create a default
|
|
constructor (i.e. a constructor that has no parameters) in the source
|
|
code definition of your class.</para>
|
|
|
|
<para>The <classname>XmlObjectFactory</classname> implementation of
|
|
the <classname>IObjectFactory</classname> interface can consume object
|
|
definitions that have been defined in XML, for example...
|
|
<programlisting><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/></programlisting></para>
|
|
|
|
<para>The mechanism for supplying arguments to the constructor (if
|
|
required), or setting properties of the object instance after it has
|
|
been constructed, is described shortly.</para>
|
|
|
|
<para>This XML fragment describes an object definition that will be
|
|
identified by the <emphasis>exampleObject</emphasis> name, instances
|
|
of which will be of the <classname>Examples.ExampleObject</classname>
|
|
type that has been compiled into the
|
|
<literal>ExamplesLibrary</literal> assembly. Take special note of the
|
|
structure of the <literal>type</literal> attribute's value... the
|
|
namespace-qualified name of the class is specified, followed by a
|
|
comma, followed by (at a bare minimum) the name of the assembly that
|
|
contains the class. In the preceding example, the
|
|
<literal>ExampleObject</literal> class is defined in the
|
|
<literal>Examples</literal> namespace, and it has been compiled into
|
|
the <literal>ExamplesLibrary</literal> assembly.</para>
|
|
|
|
<para>The name of the assembly that contains the type
|
|
<emphasis>must</emphasis> be specified in the <literal>type</literal>
|
|
attribute. Furthermore, it is recommended that you specify the fully
|
|
qualified assembly name <footnote>
|
|
<para>More information about assembly names can be found in the
|
|
<emphasis>Assembly Names</emphasis> section of the .NET Framework
|
|
Developer's Guide (installed as part of the .NET SDK), or online
|
|
at Microsoft's MSDN website, by searching for <emphasis>Assembly
|
|
Names</emphasis>.</para>
|
|
</footnote> in order to guarantee that the type that Spring.NET uses
|
|
to instantiate your object (s) is indeed the one that you expect.
|
|
Usually this is only an issue if you are using classes from (strongly
|
|
named) assemblies that have been installed into the Global Assembly
|
|
Cache (GAC).</para>
|
|
|
|
<para>If you have defined nested classes use the addition symbol, +,
|
|
to reference the nested class. For example, if the class
|
|
<literal>Examples.ExampleObject</literal> had a nested class
|
|
<literal>Person</literal> the XML declaration would be
|
|
<programlisting><object id="exampleObject" type="Examples.ExampleObject+Person, ExamplesLibrary"/></programlisting></para>
|
|
|
|
<para>If you are defining classes that have been compiled into
|
|
assemblies that are available to your application (such as the
|
|
<literal>bin</literal> directory in the case of ASP.NET applications)
|
|
via the standard assembly probing mechanisms, then you can specify
|
|
simply the name of the assembly (e.g.
|
|
<literal>ExamplesLibrary.Data</literal>)... this way, when (or if) the
|
|
assemblies used by your application are updated, you won't have to
|
|
change the value of every <literal><object/></literal>
|
|
definition's <literal>type</literal> attribute to reflect the new
|
|
version number (if the version number has changed)... Spring.NET will
|
|
automatically locate and use the newer versions of your assemblies
|
|
(and their attendant classes) from that point forward.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-factory-class-static-factory-method">
|
|
<title>Object creation via a static factory method</title>
|
|
|
|
<para>When defining an object which is to be created using a static
|
|
factory method, along with the type attribute which specifies the type
|
|
containing the static factory method, another attribute named
|
|
factory-method is needed to specify the name of the factory method
|
|
itself. Spring.NET expects to be able to call this method (with an
|
|
optional list of arguments as described later) and get back a live
|
|
object, which from that point on is treated as if it had been created
|
|
normally via a constructor. One use for such an object definition is
|
|
to call static factories in legacy code.</para>
|
|
|
|
<para>Following is an example of an object definition which specifies
|
|
that the object is to be created by calling a factory-method. Note
|
|
that the definition does not specify the type (class) of the returned
|
|
object, only the type containing the factory method. In this example,
|
|
<literal>CreateInstance</literal> must be a static method.
|
|
<programlisting><object id="exampleObject"
|
|
type="Examples.ExampleObjectFactory, ExamplesLibrary"
|
|
factory-method="CreateInstance"/></programlisting></para>
|
|
|
|
<para>The mechanism for supplying (optional) arguments to the factory
|
|
method, or setting properties of the object instance after it has been
|
|
returned from the factory, will be described shortly.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-factory-class-instance-factory-method">
|
|
<title>Object creation via an instance factory method</title>
|
|
|
|
<para>In a fashion similar to instantiation using a static factory
|
|
method, instantiation using an instance factory method is where a
|
|
non-static method of an existing object from the container is invoked
|
|
to create the new object. To use this mechanism, the
|
|
<literal>'type'</literal> attribute must be left empty, and the
|
|
<literal>'factory-object'</literal> attribute must specify the name of
|
|
an object in the current (or parent/ancestor) container that contains
|
|
the instance method that is to be invoked to create the object. The
|
|
name of the factory method itself should still be set via the
|
|
<literal>'factory-method'</literal> attribute.<programlisting><!-- the factory object, which contains an instance method called 'CreateInstance' -->
|
|
<object id="exampleFactory" type="...">
|
|
<!-- inject any dependencies required by this object -->
|
|
</object>
|
|
|
|
<!-- the object that is to be created by the factory object -->
|
|
<object id="exampleObject"
|
|
factory-method="CreateInstance"
|
|
factory-object="exampleFactory"/></programlisting></para>
|
|
|
|
<para>Although the mechanisms for setting object properties are still
|
|
to be discussed, one implication of this approach is that the factory
|
|
object itself can be managed and configured via Dependency Injection,
|
|
by the container.<note>
|
|
<para>When the Spring documentation makes mention of a 'factory
|
|
object', this will be a reference to an object that is configured
|
|
in the Spring container that will create objects via an instance
|
|
or static factory method. When the documentation mentions a
|
|
<literal>IFactoryObject</literal> (notice the capitalization) this
|
|
is a reference to a Spring-specific
|
|
<literal>IFactoryObject</literal> .</para>
|
|
</note></para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-creation-generic-types">
|
|
<title>Object creation of generic types</title>
|
|
|
|
<para>Generic types can also be created in much the same manner an
|
|
non-generic types.</para>
|
|
|
|
<sect3 id="objects-factory-generic-class-ctor">
|
|
<title>Object creation of generic types via constructor
|
|
invocation</title>
|
|
|
|
<para>The following examples shows the definition of simple generic
|
|
types and how they can be created in Spring's XML based configuration
|
|
file. <programlisting>namespace GenericsPlay
|
|
{
|
|
public class FilterableList<T>
|
|
{
|
|
private List<T> list;
|
|
|
|
private String name;
|
|
|
|
public List<T> Contents
|
|
{
|
|
get { return list; }
|
|
set { list = value; }
|
|
}
|
|
|
|
public String Name
|
|
{
|
|
get { return name; }
|
|
set { name = value; }
|
|
}
|
|
|
|
public List<T> ApplyFilter(string filterExpression)
|
|
{
|
|
/// should really apply filter to list ;)
|
|
return new List<T>();
|
|
}
|
|
|
|
}
|
|
}</programlisting> The XML configuration to create and configure this object
|
|
is shown below <programlisting><object id="myFilteredIntList" type="GenericsPlay.FilterableList&lt;int>, GenericsPlay">
|
|
<property name="Name" value="My Integer List"/>
|
|
</object></programlisting> There are a few items to note in terms how to
|
|
specify a generic type. First, the left bracket that specifies the
|
|
generic type, i.e. <literal><</literal>, is replaced with the
|
|
string &lt; due to XML escape syntax for the less than symbol.
|
|
Yes, we all realize this is less than ideal from the readability point
|
|
of view. Second, the generic type arguments can not be fully assembly
|
|
qualified as the comma is used to separate generic type arguments.
|
|
Alternative characters used to overcome the two quirks can be
|
|
implemented in the future but so far, all proposals don't seem to help
|
|
clarify the text. The suggested solution to improve readability is to
|
|
use type aliases as shown below <programlisting>
|
|
<typeAliases>
|
|
<alias name="GenericDictionary" type=" System.Collections.Generic.Dictionary&lt;,>" />
|
|
<alias name="myDictionary" type="System.Collections.Generic.Dictionary&lt;int,string>" />
|
|
</typeAliases>
|
|
</programlisting> So that instead of something like this <programlisting><object id="myGenericObject"
|
|
type="GenericsPlay.ExampleGenericObject&lt;System.Collections.Generic.Dictionary&lt;int , string>>, GenericsPlay" /></programlisting>
|
|
It can be shortened to <programlisting><object id="myOtherGenericObject"
|
|
type="GenericsPlay.ExampleGenericObject&lt;GenericDictionary&lt;int , string>>, GenericsPlay" /></programlisting>
|
|
or even shorter <programlisting><object id="myOtherOtherGenericObject"
|
|
type="GenericsPlay.ExampleGenericObject&lt;MyIntStringDictionary>, GenericsPlay" />
|
|
</programlisting> Refer to <xref linkend="context-configuration" /> for
|
|
additional information on using type aliases.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-factory-generic-static-factory">
|
|
<title>Object creation of generic types via static factory
|
|
method</title>
|
|
|
|
<para>The following classes are used to demonstrate the ability to
|
|
create instances of generic types that themselves are created via a
|
|
static generic factory method. <programlisting>public class TestGenericObject<T, U>
|
|
{
|
|
public TestGenericObject()
|
|
{
|
|
}
|
|
|
|
private IList<T> someGenericList = new List<T>();
|
|
|
|
private IDictionary<string, U> someStringKeyedDictionary =
|
|
new Dictionary<string, U>();
|
|
|
|
public IList<T> SomeGenericList
|
|
{
|
|
get { return someGenericList; }
|
|
set { someGenericList = value; }
|
|
}
|
|
|
|
public IDictionary<string, U> SomeStringKeyedDictionary
|
|
{
|
|
get { return someStringKeyedDictionary; }
|
|
set { someStringKeyedDictionary = value; }
|
|
}
|
|
|
|
}</programlisting> The accompanying factory class is <programlisting>
|
|
public class TestGenericObjectFactory
|
|
{
|
|
public static TestGenericObject<V, W> StaticCreateInstance<V, W>()
|
|
{
|
|
return new TestGenericObject<V, W>();
|
|
}
|
|
|
|
public TestGenericObject<V, W> CreateInstance<V, W>()
|
|
{
|
|
return new TestGenericObject<V, W>();
|
|
}
|
|
}
|
|
</programlisting> The XML snippet to create an instance of TestGenericObject
|
|
where <literal>V</literal> is a List of integers and
|
|
<literal>W</literal> is an integer is shown below <programlisting><object id="myTestGenericObject"
|
|
type="GenericsPlay.TestGenericObjectFactory, GenericsPlay"
|
|
factory-method="StaticCreateInstance&lt;System.Collections.Generic.List&lt;int>,int>"
|
|
/></programlisting> The StaticCreateInstance method is responsible for
|
|
instantiating the object that will be associated with the id
|
|
'myTestGenericObject'.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-factory-generic-instance-factory">
|
|
<title>Object creation of generic types via instance factory
|
|
method</title>
|
|
|
|
<para>Using the class from the previous example the XML snippet to
|
|
create an instance of a generic type via an instance factory method is
|
|
shown below <programlisting><object id="exampleFactory" type="GenericsPlay.TestGenericObject&lt;int,string>, GenericsPlay"/>
|
|
|
|
<object id="anotherTestGenericObject"
|
|
factory-object="exampleFactory"
|
|
factory-method="CreateInstance&lt;System.Collections.Generic.List&lt;int>,int>"/>
|
|
</programlisting> This creates an instance of
|
|
<literal>TestGenericObject<List<int>,int></literal></para>
|
|
</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>
|
|
|
|
<sect1 id="objects-dependencies">
|
|
<title>Dependencies</title>
|
|
|
|
<para>Your typical enterprise application is not made up of a single
|
|
object. Even the simplest of applications will no doubt have at least a
|
|
handful of objects that work together to present what the end-user sees as
|
|
a coherent application. This next section explains how you go from
|
|
defining a number of object definitions that stand-alone, each to
|
|
themselves, to a fully realized application where objects work (or
|
|
collaborate) together to achieve some goal (usually an application that
|
|
does what the end-user wants).</para>
|
|
|
|
<sect2 id="objects-factory-collaborators">
|
|
<title>Injecting dependencies</title>
|
|
|
|
<para>The basic principle behind Dependency Injection (DI) is that
|
|
objects define their dependencies (that is to say the other objects they
|
|
work with) only through constructor arguments, arguments to a factory
|
|
method, or properties which are set on the object instance after it has
|
|
been constructed or returned from a factory method. Then, it is the job
|
|
of the container to actually inject those dependencies when it creates
|
|
the object. This is fundamentally the inverse, hence the name Inversion
|
|
of Control (IoC), of the object itself being in control of instantiating
|
|
or locating its dependencies on its own using direct construction of
|
|
classes, or something like the Service Locator pattern.</para>
|
|
|
|
<para>It becomes evident upon usage that code gets much cleaner when the
|
|
DI principle is applied, and reaching a higher grade of decoupling is
|
|
much easier when objects do not look up their dependencies, but are
|
|
provided with them (and additionally do not even know where the
|
|
dependencies are located and of what concrete class they are). DI exists
|
|
in two major variants, namely Constructor Injection and Setter
|
|
Injection.</para>
|
|
|
|
<sect3 id="objects-ctor-injection">
|
|
<title>Constructor Injection</title>
|
|
|
|
<para>Constructor-based DI is effected by invoking a constructor with
|
|
a number of arguments, each representing a dependency. Additionally,
|
|
calling a static factory method with specific arguments to construct
|
|
the object, can be considered almost equivalent, and the rest of this
|
|
text will consider arguments to a constructor and arguments to a
|
|
static factory method similarly. Find below an example of a class that
|
|
could only be dependency injected using constructor injection. Notice
|
|
that there is nothing special about this class.</para>
|
|
|
|
<programlisting>public class SimpleMovieLister
|
|
{
|
|
// the SimpleMovieLister has a dependency on a MovieFinder
|
|
private IMovieFinder movieFinder;
|
|
|
|
// a constructor so that the Spring container can 'inject' a MovieFinder
|
|
public MovieLister(IMovieFinder movieFinder)
|
|
{
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
|
|
// business logic that actually 'uses' the injected IMovieFinder is omitted...
|
|
|
|
}</programlisting>
|
|
|
|
<sect4 id="objects-ctor-arg-resolution">
|
|
<title>Constructor Argument Resolution</title>
|
|
|
|
<para>Constructor argument resolution matching occurs using the
|
|
argument's type. If there is no potential for ambiguity in the
|
|
constructor arguments of a object definition, then the order in
|
|
which the constructor arguments are defined in a object definition
|
|
is the order in which those arguments will be supplied to the
|
|
appropriate constructor when it is being instantiated. Consider the
|
|
following class:</para>
|
|
|
|
<programlisting>namespace X.Y
|
|
{
|
|
public class Foo
|
|
{
|
|
public Foo(Bar bar, Baz baz)
|
|
{
|
|
// ...
|
|
}
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>There is no potential for ambiguity here (assuming of course
|
|
that Bar and Baz classes are not related in an inheritance
|
|
hierarchy). Thus the following configuration will work just fine,
|
|
and you do not need to specify the constructor argument indexes and
|
|
/ or types explicitly.</para>
|
|
|
|
<programlisting><object name="Foo" type="X.Y.Foo, Example">
|
|
<constructor-arg>
|
|
<object type="X.Y.Bar, Example"/>
|
|
</constructor-arg>
|
|
<constructor-arg>
|
|
<object type="X.Y.Baz, Example"/>
|
|
</constructor-arg>
|
|
</object></programlisting>
|
|
|
|
<para>When another object is referenced, the type is known, and
|
|
matching can occur (as was the case with the preceding example).
|
|
When a simple type is used, such as
|
|
<literal><value>true<value></literal>, Spring cannot
|
|
determine the type of the value, and so cannot match by type without
|
|
help. Consider the following class:</para>
|
|
|
|
<programlisting>using System;
|
|
|
|
namespace SimpleApp
|
|
{
|
|
public class ExampleObject
|
|
{
|
|
private int years; //No. of years to the calculate the Ultimate Answer
|
|
|
|
private string ultimateAnswer; //The Answer to Life, the Universe, and Everything
|
|
|
|
public ExampleObject(int years, string ultimateAnswer)
|
|
{
|
|
this.years = years;
|
|
this.ultimateAnswer = ultimateAnswer;
|
|
}
|
|
|
|
}</programlisting>
|
|
|
|
<sect5 id="objects-ctor-arg-type-matching">
|
|
<title>Constructor Argument Type Matching</title>
|
|
|
|
<para>The above scenario <emphasis>can</emphasis> use type
|
|
matching with simple types by explicitly specifying the type of
|
|
the constructor argument using the <literal>type</literal>
|
|
attribute. For example: <programlisting><object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
|
|
<constructor-arg type="int" value="7500000"/>
|
|
<constructor-arg type="string" value="42"/>
|
|
</object></programlisting></para>
|
|
|
|
<para>The type attribute specifies the
|
|
<literal>System.Type</literal> of the constructor argument, such
|
|
as System.Int32. Alias' are available to for common simple types
|
|
(and their array equivalents). These alias' are... <table
|
|
frame="all">
|
|
<title>Type aliases</title>
|
|
|
|
<tgroup cols="3">
|
|
<colspec colname="c1" colwidth="1*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<colspec colname="c3" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Type</entry>
|
|
|
|
<entry>Alias'</entry>
|
|
|
|
<entry>Array Alias'</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>System.Char</entry>
|
|
|
|
<entry>char, Char</entry>
|
|
|
|
<entry>char[], Char()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Int16</entry>
|
|
|
|
<entry>short, Short</entry>
|
|
|
|
<entry>short[], Short()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Int32</entry>
|
|
|
|
<entry>int, Integer</entry>
|
|
|
|
<entry>int[], Integer()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Int64</entry>
|
|
|
|
<entry>long, Long</entry>
|
|
|
|
<entry>long[], Long()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.UInt16</entry>
|
|
|
|
<entry>ushort</entry>
|
|
|
|
<entry>ushort[]</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.UInt32</entry>
|
|
|
|
<entry>uint</entry>
|
|
|
|
<entry>uint[]</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.UInt64</entry>
|
|
|
|
<entry>ulong</entry>
|
|
|
|
<entry>ulong[]</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Float</entry>
|
|
|
|
<entry>float, Single</entry>
|
|
|
|
<entry>float[], Single()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Double</entry>
|
|
|
|
<entry>double, Double</entry>
|
|
|
|
<entry>double[], Double()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Date</entry>
|
|
|
|
<entry>date, Date</entry>
|
|
|
|
<entry>date[], Date()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Decimal</entry>
|
|
|
|
<entry>decimal, Decimal</entry>
|
|
|
|
<entry>decimal[], Decimal()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Bool</entry>
|
|
|
|
<entry>bool, Boolean</entry>
|
|
|
|
<entry>bool[], Boolean()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.String</entry>
|
|
|
|
<entry>string, String</entry>
|
|
|
|
<entry>string[], String()</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
</sect5>
|
|
|
|
<sect5 id="objects-ctor-arg-index">
|
|
<title>Constructor Argument Index</title>
|
|
|
|
<para>Constructor arguments can have their index specified
|
|
explicitly by use of the <literal>index</literal> attribute. For
|
|
example: <programlisting><object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
|
|
<constructor-arg index="0" value="7500000"/>
|
|
<constructor-arg index="1" value="42"/>
|
|
</object></programlisting>As well as solving the ambiguity problem of
|
|
multiple simple values, specifying an index also solves the
|
|
problem of ambiguity where a constructor may have two arguments of
|
|
the same type. Note that the <emphasis>index is 0
|
|
based</emphasis>.</para>
|
|
</sect5>
|
|
|
|
<sect5 id="objects-ctor-arg-by-name">
|
|
<title>Constructor Arguments by Name</title>
|
|
|
|
<para>Constructor arguments can also be specified by name by using
|
|
the <literal>name</literal> attribute of the
|
|
<literal><constructor-arg></literal> element.</para>
|
|
|
|
<programlisting><object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
|
|
<constructor-arg name="years" value="7500000"/>
|
|
<constructor-arg name="ultimateAnswer" value="42"/>
|
|
</object></programlisting>
|
|
</sect5>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-setter-injection">
|
|
<title>Setter Injection</title>
|
|
|
|
<para>Setter-based DI is realized by calling setter methods on your
|
|
objects after invoking a no-argument constructor or no-argument static
|
|
factory method to instantiate your object.</para>
|
|
|
|
<para>Find below an example of a class that can only be dependency
|
|
injected using pure setter injection.</para>
|
|
|
|
<programlisting>public class MovieLister
|
|
{
|
|
private IMovieFinder movieFinder;
|
|
|
|
public IMovieFinder MovieFinder
|
|
{
|
|
set
|
|
{
|
|
movieFinder = value;
|
|
}
|
|
}
|
|
|
|
// business logic that actually 'uses' the injected IMovieFinder is omitted...
|
|
}</programlisting>
|
|
|
|
<sidebar>
|
|
<title>Constructor- or Setter-based DI?</title>
|
|
|
|
<para>The Spring team generally advocates the usage of setter
|
|
injection, since a large number of constructor arguments can get
|
|
unwieldy, especially when some properties are optional. The presence
|
|
of setter methods also makes objects of that class amenable to being
|
|
re-configured (or re-injected) at some later time (for management
|
|
purposes).</para>
|
|
|
|
<para>Constructor-injection is favored by some purists though and
|
|
with good reason. Supplying all of an object's dependencies means
|
|
that that object is never returned to client (calling) code in a
|
|
less than totally initialized state. The flip side is that the
|
|
object becomes less amenable to re-configuration (or
|
|
re-injection).</para>
|
|
|
|
<para>There is no hard and fast rule here. Use whatever type of DI
|
|
makes the most sense for a particular class; sometimes, when dealing
|
|
with third party classes to which you do not have the source, the
|
|
choice will already have been made for you - a legacy class may not
|
|
expose any setter methods, and so constructor injection will be the
|
|
only type of DI available to you.</para>
|
|
</sidebar>
|
|
|
|
<para>The <classname>IObjectFactory</classname> supports both of these
|
|
variants for injecting dependencies into objects it manages. (It in
|
|
fact also supports injecting setter-based dependencies after some
|
|
dependencies have already been supplied via the constructor approach.)
|
|
The configuration for the dependencies comes in the form of the
|
|
<classname>IObjectDefinition</classname> class, which is used together
|
|
with <literal>TypeConverters</literal> to know how to convert
|
|
properties from one format to another. However, most users of
|
|
Spring.NET will not be dealing with these classes directly (that is
|
|
programatically), but rather with an XML definition file which will be
|
|
converted internally into instances of these classes, and used to load
|
|
an entire Spring IoC container instance.</para>
|
|
|
|
<para>Object dependency resolution generally happens as follows:
|
|
<orderedlist spacing="compact">
|
|
<listitem>
|
|
<para>The <classname>IObjectFactory</classname> is created and
|
|
initialized with a configuration which describes all the
|
|
objects. Most Spring.NET users use an
|
|
<classname>IObjectFactory</classname> or
|
|
<classname>IApplicationContext</classname> variant that supports
|
|
XML format configuration files.</para>
|
|
|
|
<para></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Each object has dependencies expressed in the form of
|
|
properties, constructor arguments, or arguments to the
|
|
static-factory method when that is used instead of a normal
|
|
constructor. These dependencies will be provided to the object,
|
|
<emphasis>when the object is actually created</emphasis>.</para>
|
|
|
|
<para></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Each property or constructor argument is either an actual
|
|
definition of the value to set, or a reference to another object
|
|
in the container.</para>
|
|
|
|
<para></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><anchor
|
|
id="object-factory-collaborators-typeconverter" />Each property
|
|
or constructor argument which is a value must be able to be
|
|
converted from whatever format it was specified in, to the
|
|
actual <classname>System.Type</classname> of that property or
|
|
constructor argument. By default Spring.NET can convert a value
|
|
supplied in string format to all built-in types, such as
|
|
<literal>int</literal>, <literal>long</literal>,
|
|
<literal>string</literal>, <literal>bool</literal>, etc.
|
|
Spring.NET uses <classname>TypeConverter</classname> definitions
|
|
to be able to convert string values to other, arbitrary types.
|
|
Refer to <xref linkend="objects-objects-conversion" /> for more
|
|
information regarding type conversion, and how you can design
|
|
your classes to be convertible by Spring.NET.</para>
|
|
</listitem>
|
|
</orderedlist></para>
|
|
|
|
<para>The Spring container validates the configuration of each object
|
|
as the container is created, including the validation that properties
|
|
which are object references are actually referring to valid object.
|
|
However, the object properties themselves are not set until the object
|
|
is actually created. For those object that defined as singletons and
|
|
set to be pre-instantiated (such as singleton object in an
|
|
<classname>IApplicationContext</classname>), creation happens at the
|
|
time that the container is created, but otherwise this is only when
|
|
the object is requested. When an object actually has to be created,
|
|
this will potentially cause a graph of other objects to be created, as
|
|
its dependencies and its dependencies' dependencies (and so on) are
|
|
created and assigned.</para>
|
|
|
|
<sidebar>
|
|
<title>Circular Dependencies</title>
|
|
|
|
<para>If you are using predominantly constructor injection it is
|
|
possible to write and configure your classes and objects such that
|
|
an unresolvable circular dependency scenario is created.</para>
|
|
|
|
<para>Consider the scenario where you have class A, which requires
|
|
an instance of class B to be provided via constructor injection, and
|
|
class B, which requires an instance of class A to be provided via
|
|
constructor injection. If you configure object for classes A and B
|
|
to be injected into each other, the Spring IoC container will detect
|
|
this circular reference at runtime, and throw a
|
|
<classname>ObjectCurrentlyInCreationException</classname>.</para>
|
|
|
|
<para>One possible solution to this issue is to edit the source code
|
|
of some of your classes to be configured via setters instead of via
|
|
constructors. Another solution is not to use constructor injection
|
|
and stick to setter injection only. In other words, while it should
|
|
generally be avoided in all but the rarest of circumstances, it is
|
|
possible to configure circular dependencies with setter
|
|
injection.</para>
|
|
|
|
<para>Unlike the typical case (with no circular dependencies), a
|
|
circular dependency between object A and object B will force one of
|
|
the objects to be injected into the other prior to being fully
|
|
initialized itself (a classic chicken/egg scenario).</para>
|
|
</sidebar>
|
|
|
|
<para>You can generally trust Spring.NET to do the right thing. It
|
|
will detect configuration issues, such as references to non-existent
|
|
object definitions and circular dependencies, at container load-time.
|
|
It will actually set properties and resolve dependencies as late as
|
|
possible, which is when the object is actually created. This means
|
|
that a Spring container which has loaded correctly can later generate
|
|
an exception when you request an object if there is a problem creating
|
|
that object or one of its dependencies. This could happen if the
|
|
object throws an exception as a result of a missing or invalid
|
|
property, for example. This potentially delayed visibility of some
|
|
configuration issues is why <classname>IApplicationContext</classname>
|
|
by default pre-instantiates singleton objects. At the cost of some
|
|
upfront time and memory to create these objects before they are
|
|
actually needed, you find out about configuration issues when the
|
|
<classname>IApplicationContext</classname> is created, not later. If
|
|
you wish, you can still override this default behavior and set any of
|
|
these singleton objects to lazy-load (not be preinstantiated)</para>
|
|
|
|
<para>If no circular dependencies are involved (see sidebar for a
|
|
discussion of circular dependencies), when one or more collaborating
|
|
objects are being injected into a dependent object, each collaborating
|
|
object is totally configured prior to being passed (via one of the DI
|
|
flavors) to the dependent object. This means that if object A has a
|
|
dependency on object B, the Spring IoC container will
|
|
<emphasis>totally</emphasis> configure object B prior to invoking the
|
|
setter method on object A; you can read<emphasis> 'totally
|
|
configure'</emphasis> to mean that the object will be instantiated (if
|
|
not a pre-instantiated singleton), all of its dependencies will be
|
|
set, and the relevant lifecycle methods (such as a configured init
|
|
method or the <classname>IIntializingObject</classname> callback
|
|
method) will all be invoked.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-di-examples">
|
|
<title>Some examples</title>
|
|
|
|
<para>First, an example of using XML-based configuration metadata for
|
|
setter-based DI. Find below a smallpart of a Spring XML configuration
|
|
file specifying some object definitions. <programlisting><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary">
|
|
|
|
<!-- setter injection using the ref attribute -->
|
|
<property name="objectOne" ref="anotherExampleObject"/>
|
|
<property name="objectTwo" ref="yetAnotherObject"/>
|
|
<property name="IntegerProperty" value="1"/>
|
|
</object>
|
|
|
|
<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
|
|
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/></programlisting>
|
|
<programlisting>[C#]
|
|
public class ExampleObject
|
|
{
|
|
private AnotherObject objectOne;
|
|
private YetAnotherObject objectTwo;
|
|
private int i;
|
|
|
|
public AnotherObject ObjectOne
|
|
{
|
|
set { this.objectOne = value; }
|
|
}
|
|
|
|
public YetAnotherObject ObjectTwo
|
|
{
|
|
set { this.objectTwo = value; }
|
|
}
|
|
|
|
public int IntegerProperty
|
|
{
|
|
set { this.i = value; }
|
|
}
|
|
}</programlisting></para>
|
|
|
|
<para>As you can see, setters have been declared to match against the
|
|
properties specified in the XML file. Find below an example of using
|
|
constructor-based DI.<programlisting><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary">
|
|
<constructor-arg name="objectOne" ref="anotherExampleObject"/>
|
|
<constructor-arg name="objectTwo" ref="yetAnotherObject"/>
|
|
<constructor-arg name="IntegerProperty" value="1"/>
|
|
</object>
|
|
|
|
<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
|
|
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/></programlisting>
|
|
<programlisting>[Visual Basic.NET]
|
|
Public Class ExampleObject
|
|
|
|
Private myObjectOne As AnotherObject
|
|
Private myObjectTwo As YetAnotherObject
|
|
Private i As Integer
|
|
|
|
Public Sub New (
|
|
anotherObject as AnotherObject,
|
|
yetAnotherObject as YetAnotherObject,
|
|
i as Integer)
|
|
|
|
myObjectOne = anotherObject
|
|
myObjectTwo = yetAnotherObject
|
|
Me.i = i
|
|
End Sub
|
|
End Class</programlisting>As you can see, the constructor arguments specified
|
|
in the object definition will be used to pass in as arguments to the
|
|
constructor of the <classname>ExampleObject</classname>.</para>
|
|
|
|
<para>Now consider a variant of this where instead of using a
|
|
constructor, Spring is told to call a static factory method to return
|
|
an instance of the object <programlisting><object id="exampleObject" type="Examples.ExampleFactoryMethodObject, ExamplesLibrary"
|
|
factory-method="CreateInstance">
|
|
<constructor-arg name="objectOne" ref="anotherExampleObject"/>
|
|
<constructor-arg name="objectTwo" ref="yetAnotherObject"/>
|
|
<constructor-arg name="intProp" value="1"/>
|
|
</object>
|
|
|
|
<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
|
|
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/></programlisting>
|
|
<programlisting>[C#]
|
|
public class ExampleFactoryMethodObject
|
|
{
|
|
private AnotherObject objectOne;
|
|
private YetAnotherObject objectTwo;
|
|
private int i;
|
|
|
|
// a private constructor
|
|
private ExampleFactoryMethodObject()
|
|
{
|
|
}
|
|
|
|
public static ExampleFactoryMethodObject CreateInstance(AnotherObject objectOne,
|
|
YetAnotherObject objectTwo,
|
|
int intProp)
|
|
{
|
|
ExampleFactoryMethodObject fmo = new ExampleFactoryMethodObject();
|
|
fmo.AnotherObject = objectOne;
|
|
fmo.YetAnotherObject = objectTwo;
|
|
fmo.IntegerProperty = intProp;
|
|
return fmo;
|
|
}
|
|
|
|
// Property definitions
|
|
|
|
}</programlisting> Note that arguments to the static factory method are
|
|
supplied via constructor-arg elements, exactly the same as if a
|
|
constructor had actually been used. These arguments are optional.
|
|
Also, it is important to realize that the type of the class being
|
|
returned by the factory method does not have to be of the same type as
|
|
the class which contains the static factory method, although in this
|
|
example it is. An instance (non-static) factory method, mentioned
|
|
previously, would be used in an essentially identical fashion (aside
|
|
from the use of the factory-object attribute instead of the type
|
|
attribute), so will not be detailed here.</para>
|
|
|
|
<para>Note that Setter Injection and Constructor Injectionare not
|
|
mutually exclusive. It is perfectly reasonable to use both for a
|
|
single object definition, as can be seen in the following example:
|
|
<programlisting><object id="exampleObject" type="Examples.MixedIocObject, ExamplesLibrary">
|
|
<constructor-arg name="objectOne" ref="anotherExampleObject"/>
|
|
<property name="objectTwo" ref="yetAnotherObject"/>
|
|
<property name="IntegerProperty" value="1"/>
|
|
</object>
|
|
|
|
<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
|
|
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/></programlisting>
|
|
<programlisting>[C#]
|
|
public class MixedIocObject
|
|
{
|
|
private AnotherObject objectOne;
|
|
private YetAnotherObject objectTwo;
|
|
private int i;
|
|
|
|
public MixedIocObject (AnotherObject obj)
|
|
{
|
|
this.objectOne = obj;
|
|
}
|
|
|
|
public YetAnotherObject ObjectTwo
|
|
{
|
|
set { this.objectTwo = value; }
|
|
}
|
|
|
|
public int IntegerProperty
|
|
{
|
|
set { this.i = value; }
|
|
}
|
|
}</programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 id="object-factory-properties-detailed">
|
|
<title>Dependencies and configuration in detail</title>
|
|
|
|
<para>As mentioned in the previous section, object properties and
|
|
constructor arguments can be defined as either references to other
|
|
managed objects (collaborators), or values defined inline. Spring's
|
|
XML-based configuration metadata supports a number of sub-element types
|
|
within its <literal><property/></literal> and
|
|
<<literal>constructor-arg/></literal> elements for this
|
|
purpose.a</para>
|
|
|
|
<sect3>
|
|
<title>Straight values (primitives, <literal>strings</literal>,
|
|
etc.)</title>
|
|
|
|
<para>The <literal><value/></literal> element specifies a
|
|
property or constructor argument as a human-readable string
|
|
representation. As mentioned previously,
|
|
<classname>TypeConverter</classname> instances are used to convert
|
|
these string values from a <classname>System.String</classname> to the
|
|
actual property or argument type. Custom
|
|
<classname>TypeConverter</classname> implementations in the
|
|
<literal>Spring.Objects.TypeConverters</literal> namespace are used to
|
|
augment the functionality offered by the .NET BCL's default
|
|
<classname>TypeConverter</classname> implementations.</para>
|
|
|
|
<para>In the following example, we use a
|
|
<classname>SqlConnection</classname> from the
|
|
<literal>System.Data.SqlClient</literal> namespace of the BCL. This
|
|
class (like many other existing classes) can easily be used in a
|
|
Spring.NET object factory, as it offers a convenient public property
|
|
for configuration of its <literal>ConnectionString</literal>
|
|
property.</para>
|
|
|
|
<para>
|
|
<programlisting format="linespecific" xml:space="preserve">objects xmlns="http://www.springframework.net">
|
|
<object id="myConnection" type="System.Data.SqlClient.SqlConnection">
|
|
<!-- results in a call to the setter of the ConnectionString property -->
|
|
<property
|
|
name="ConnectionString"
|
|
value="Integrated Security=SSPI;database=northwind;server=mySQLServer"/>
|
|
</object>
|
|
</objects></programlisting>
|
|
</para>
|
|
|
|
<sect4>
|
|
<title>The idref element</title>
|
|
|
|
<para>An idref element is simply a shorthand and error-proof way to
|
|
set a property to the String <emphasis>id</emphasis> or
|
|
<emphasis>name</emphasis> of another object in the
|
|
container.<programlisting><object id="theTargetObject" type="...">
|
|
. . .
|
|
</object>
|
|
|
|
<object id="theClientObject" type="...">
|
|
<property name="targetName">
|
|
<idref object="theTargetObject"/>
|
|
</property>
|
|
</object></programlisting>This is exactly equivalent at runtime to the
|
|
following fragment:<programlisting><object id="theTargetObject" type="...">
|
|
. . .
|
|
</object>
|
|
|
|
<object id="theClientObject" type="...">
|
|
<property name="targetName" value="theTargetObject"/>
|
|
</object></programlisting>The main reason the first form is preferable
|
|
to the second is that using the <literal>idref</literal> tag will
|
|
allow Spring.NET to validate at deployment time that the other
|
|
object actually exists. In the second variation, the class that is
|
|
having its <emphasis>targetName</emphasis> property injected is
|
|
forced to do its own validation, and that will only happen when that
|
|
class is actually instantiated by the container, possibly long after
|
|
the container is actually up and running.</para>
|
|
|
|
<para>Additionally, if the object being referred to is in the same
|
|
actual XML file, and the object name is the object
|
|
<emphasis>id</emphasis>, the <literal>local</literal> attribute may
|
|
be used, which will allow the XML parser itself to validate the
|
|
object name even earlier, at parse time. <programlisting><property name="targetName">
|
|
<idref local="theTargetObject"/>
|
|
</property></programlisting></para>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-ref-element">
|
|
<title>Referring to collaborating objects</title>
|
|
|
|
<para>The <literal>ref</literal> element is the final element allowed
|
|
inside a <literal>property</literal> definition element. It is used to
|
|
set the value of the specified property to be a reference to another
|
|
object managed by the container, a collaborator, so to speak. As you
|
|
saw in the previous example to set collection properties, we used the
|
|
<classname>SqlConnection</classname> instance from the initial example
|
|
as a collaborator and specified it using a <ref object/>
|
|
element. As mentioned in a previous section, the referred-to object is
|
|
considered to be a dependency of the object who's property is being
|
|
set, and will be initialized on demand as needed (if it is a singleton
|
|
object it may have already been initialized by the container) before
|
|
the property is set. All references are ultimately just a reference to
|
|
another object, but there are 3 variations on how the id/name of the
|
|
other object may be specified, which determines how scoping and
|
|
validation is handled.</para>
|
|
|
|
<para>Specifying the target object by using the
|
|
<literal>object</literal> attribute of the <literal>ref</literal> tag
|
|
is the most general form, and will allow creating a reference to any
|
|
object in the same <classname>IObjectFactory</classname> /
|
|
<classname>IApplicationContext</classname> (whether or not in the same
|
|
XML file), or parent <classname>IObjectFactory</classname> /
|
|
<classname>IApplicationContext</classname>. The value of the
|
|
<literal>object</literal> attribute may be the same as either the
|
|
<literal>id</literal> attribute of the target object, or one of the
|
|
values in the <literal>name</literal> attribute of the target
|
|
object.<programlisting><ref object="someObject"/></programlisting></para>
|
|
|
|
<para>Specifying the target object by using the
|
|
<literal>local</literal> attribute leverages the ability of the XML
|
|
parser to validate XML id references within the same file. The value
|
|
of the <literal>local</literal> attribute must be the same as the
|
|
<literal>id</literal> attribute of the target object. The XML parser
|
|
will issue an error if no matching element is found in the same file.
|
|
As such, using the local variant is the best choice (in order to know
|
|
about errors are early as possible) if the target object is in the
|
|
same XML file.<programlisting><ref local="someObject"/></programlisting></para>
|
|
|
|
<para>Specifying the target object by using the
|
|
<literal>parent</literal> attribute allows a reference to be created
|
|
to an object that is in a parent <classname>IObjectFactory</classname>
|
|
(or<classname>IApplicationContext</classname>) of the current
|
|
<classname>IObjectFactory</classname> (or
|
|
<classname>IApplicationContext</classname>). The value of the
|
|
<literal>parent</literal> attribute may be the same as either the
|
|
<literal>id</literal> attribute of the target object, or one of the
|
|
values in the <literal>name</literal> attribute of the target object,
|
|
and the target object <emphasis role="bold">must</emphasis> be in a
|
|
parent <classname>IObjectFactory</classname> or
|
|
<classname>IApplicationContext</classname> of the current one. The
|
|
main use of this object reference variant is when there is a need to
|
|
wrap an existing object in a parent context with some sort of proxy
|
|
(which may have the same name as the parent), and needs the original
|
|
object so it may wrap it.</para>
|
|
|
|
<para>
|
|
<programlisting><ref parent="someObject"/></programlisting>
|
|
</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-inline-object">
|
|
<title>Inline objects</title>
|
|
|
|
<para>An <literal>object</literal> element inside the
|
|
<literal>property</literal> element is used to define an object value
|
|
inline, instead of referring to an object defined elsewhere in the
|
|
container. The inline object definition does not need to have any id
|
|
or name defined (indeed, if any are defined, they will be ignored).
|
|
<programlisting><object id="outer" type="...">
|
|
|
|
<!-- Instead of using a reference to target, just use an inner object -->
|
|
|
|
<property name="target">
|
|
<object type="ExampleApp.Person, ExampleApp">
|
|
<property name="name" value="Tony"/>
|
|
<property name="age" value="51"/>
|
|
</object>
|
|
</property>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-collections-values">
|
|
<title>Setting collection values</title>
|
|
|
|
<para>The <literal>list</literal>, <literal>set</literal>,
|
|
<literal>name-values</literal> and <literal>dictionary</literal>
|
|
elements allow properties and arguments of the type
|
|
<literal>IList</literal>, <literal>ISet</literal>,
|
|
<literal>NameValueCollection</literal> and
|
|
<literal>IDictionary</literal>, respectively, to be defined and set.
|
|
<programlisting format="linespecific" xml:space="preserve"><objects xmlns="http://www.springframework.net">
|
|
<object id="moreComplexObject" type="Example.ComplexObject">
|
|
<!--
|
|
results in a call to the setter of the SomeList (System.Collections.IList) property
|
|
-->
|
|
<property name="SomeList">
|
|
<list>
|
|
<value>a list element followed by a reference</value>
|
|
<ref object="myConnection"/>
|
|
</list>
|
|
</property>
|
|
<!--
|
|
results in a call to the setter of the SomeDictionary (System.Collections.IDictionary) property
|
|
-->
|
|
<property name="SomeDictionary">
|
|
<dictionary>
|
|
<entry key="a string => string entry" value="just some string"/>
|
|
<entry key-ref="myKeyObject" value-ref="myConnection"/>
|
|
</dictionary>
|
|
</property>
|
|
<!--
|
|
results in a call to the setter of the SomeNameValue (System.Collections.NameValueCollection) property
|
|
-->
|
|
<property name="SomeNameValue">
|
|
<name-values>
|
|
<add key="HarryPotter" value="The magic property"/>
|
|
<add key="JerrySeinfeld" value="The funny (to Americans) property"/>
|
|
</name-values>
|
|
</property>
|
|
<!--
|
|
results in a call to the setter of the SomeSet (Spring.Collections.ISet) property
|
|
-->
|
|
<property name="someSet">
|
|
<set>
|
|
<value>just some string</value>
|
|
<ref object="myConnection"/>
|
|
</set>
|
|
</property>
|
|
</object>
|
|
</objects></programlisting></para>
|
|
|
|
<para>Many classes in the BCL expose only read-only properties for
|
|
collection classes. When Spring.NET encounters a read-only collection,
|
|
it will configure the collection by using the getter property to
|
|
obtain a reference to the collection class and then proceed to add the
|
|
additional elements to the existing collection. This results in an
|
|
additive behavior for collection properties that are exposed in this
|
|
manner.</para>
|
|
|
|
<para>
|
|
<emphasis>Note that the value of a Dictionary entry, or a set value,
|
|
can also again be any of the elements:</emphasis>
|
|
|
|
<programlisting>(object | ref | idref | expression | list | set | dictionary |
|
|
name-values | value | null)</programlisting>
|
|
</para>
|
|
|
|
<para>The shortcut forms for value and references are useful to reduce
|
|
XML verbosity when setting collection properties. See <xref
|
|
linkend="objects-shortcutforms" /> for more information.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-generic-collections-values">
|
|
<title>Setting generic collection values</title>
|
|
|
|
<para>Spring supports setting values for classes that expose
|
|
properties based on the generic collection interfaces
|
|
<classname>IList<T></classname> and
|
|
<classname>IDictionary<TKey, TValue></classname>. The type
|
|
parameter for these collections is specified by using the XML
|
|
attribute <literal>element-type</literal> for
|
|
<classname>IList<T></classname> and the XML attributes
|
|
<literal>key-type</literal> and <literal>value-type</literal> for
|
|
<classname>IDictionary<TKey, TValue></classname>. The values of
|
|
the collection are automaticaly converted from a string to the
|
|
appropriate type. If you are using your own user-defined type as a
|
|
generic type parameter you will likely need to register a custom type
|
|
converter. Refer to <xref linkend="objects-type-conversion" /> for
|
|
more information. The implementations of
|
|
<classname>IList<T></classname> and
|
|
<classname>IDictionary<TKey, TValue></classname> that is created
|
|
are <classname>System.Collections.Generic.List</classname> and
|
|
<classname>System.Collections.Generic.Dictionary</classname>.</para>
|
|
|
|
<para>The following class represents a lottery ticket and demonstrates
|
|
how to set the values of a generic IList. <programlisting>public class LotteryTicket {
|
|
|
|
List<int> list;
|
|
|
|
DateTime date;
|
|
|
|
public List<int> Numbers {
|
|
set { list = value; }
|
|
get { return list; }
|
|
}
|
|
|
|
public DateTime Date {
|
|
get { return date; }
|
|
set { date = value; }
|
|
}
|
|
}</programlisting> The XML fragment that can be used to configure this class
|
|
is shown below <programlisting><object id="MyLotteryTicket" type="GenericsPlay.Lottery.LotteryTicket, GenericsPlay">
|
|
<property name="Numbers">
|
|
<list element-type="int">
|
|
<value>11</value>
|
|
<value>21</value>
|
|
<value>23</value>
|
|
<value>34</value>
|
|
<value>36</value>
|
|
<value>38</value>
|
|
</list>
|
|
</property>
|
|
<property name="Date" value="4/16/2006"/>
|
|
</object></programlisting></para>
|
|
|
|
<para>The following shows the definition of a more complex class that
|
|
demonstrates the use of generics using the
|
|
<classname>Spring.Expressions.IExpression</classname> interface as the
|
|
generic type parameter for the IList element-type and the value-type
|
|
for IDictionary. <classname>Spring.Expressions.IExpression</classname>
|
|
has an associated type converter,
|
|
<classname>Spring.Objects.TypeConverters.ExpressionConverter</classname>
|
|
that is already pre-registered with Spring. <programlisting> public class GenericExpressionHolder
|
|
{
|
|
private System.Collections.Generic.IList<IExpression> expressionsList;
|
|
|
|
private System.Collections.Generic.IDictionary<string,IExpression> expressionsDictionary;
|
|
|
|
public System.Collections.Generic.IList<IExpression> ExpressionsList
|
|
{
|
|
set { this.expressionsList = value; }
|
|
}
|
|
|
|
public System.Collections.Generic.IDictionary<string, IExpression> ExpressionsDictionary
|
|
{
|
|
set { this.expressionsDictionary = value; }
|
|
}
|
|
|
|
public IExpression this[int index]
|
|
{
|
|
get
|
|
{
|
|
return this.expressionsList[index];
|
|
}
|
|
}
|
|
|
|
public IExpression this[string key]
|
|
{
|
|
get { return this.expressionsDictionary[key]; }
|
|
}
|
|
}</programlisting> An example XML configuration of this class is shown
|
|
below <programlisting><object id="genericExpressionHolder"
|
|
type="Spring.Objects.Factory.Xml.GenericExpressionHolder,
|
|
Spring.Core.Tests">
|
|
<property name="ExpressionsList">
|
|
<list element-type="Spring.Expressions.IExpression, Spring.Core">
|
|
<value>1 + 1</value>
|
|
<value>date('1856-7-9').Month</value>
|
|
<value>'Nikola Tesla'.ToUpper()</value>
|
|
<value>DateTime.Today > date('1856-7-9')</value>
|
|
</list>
|
|
</property>
|
|
<property name="ExpressionsDictionary">
|
|
<dictionary key-type="string" value-type="Spring.Expressions.IExpression, Spring.Core">
|
|
<entry key="zero">
|
|
<value>1 + 1</value>
|
|
</entry>
|
|
<entry key="one">
|
|
<value>date('1856-7-9').Month</value>
|
|
</entry>
|
|
<entry key="two">
|
|
<value>'Nikola Tesla'.ToUpper()</value>
|
|
</entry>
|
|
<entry key="three">
|
|
<value>DateTime.Today > date('1856-7-9')</value>
|
|
</entry>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-null-values">
|
|
<title>Setting null values</title>
|
|
|
|
<para>The <literal><null></literal> element is used to handle
|
|
<literal>null</literal> values. Spring.NET treats empty arguments for
|
|
properties and constructor arguments as empty
|
|
<classname>string</classname> instances. The following configuration
|
|
demonstrates this behaviour...</para>
|
|
|
|
<programlisting><object type="Examples.ExampleObject, ExamplesLibrary">
|
|
<property name="email"><value></value></property>
|
|
|
|
<!-- equivalent, using value attribute as opposed to nested <value/> element...
|
|
<property name="email" value=""/>
|
|
</object></programlisting>
|
|
|
|
<para>This results in the email property being set to the empty string
|
|
value (<literal>""</literal>), in much the same way as can be seen in
|
|
the following snippet of C# code... <programlisting>exampleObject.Email = "";</programlisting>
|
|
The special <literal><null/></literal> element may be used to
|
|
indicate a <literal>null</literal> value; to wit...</para>
|
|
|
|
<programlisting><object type="Examples.ExampleObject, ExamplesLibrary">
|
|
<property name="email"><null/></property>
|
|
</object></programlisting>
|
|
|
|
<para>This results in the email property being set to
|
|
<literal>null</literal>, again in much the same way as can be seen in
|
|
the following snippet of C# code... <programlisting>exampleObject.Email = null;</programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Setting indexer properties</title>
|
|
|
|
<para>An indexer lets you set and get values from a collection using a
|
|
familiar bracket <literal>[]</literal> notation. Spring's XML
|
|
configuration supports the setting of indexer properties. Overloaded
|
|
indexers as well as multiparameter indexers are also supported. The
|
|
property expression parser described in <xref linkend="expressions" />
|
|
is used to perform the type conversion of the indexer name argument
|
|
from a string in the XML file to a matching target type. As an example
|
|
consider the following class <programlisting>public class Person
|
|
{
|
|
private IList favoriteNames = new ArrayList();
|
|
|
|
private IDictionary properties = new Hashtable();
|
|
|
|
public Person()
|
|
{
|
|
favoriteNames.Add("p1");
|
|
favoriteNames.Add("p2");
|
|
}
|
|
|
|
public string this[int index]
|
|
{
|
|
get { return (string) favoriteNames[index]; }
|
|
set { favoriteNames[index] = value; }
|
|
}
|
|
|
|
public string this[string keyName]
|
|
{
|
|
get { return (string) properties[keyName]; }
|
|
set { properties.Add(keyName, value); }
|
|
}
|
|
}</programlisting> The XML configuration snippet to populate this object with
|
|
data is shown below <programlisting><object id="person" type="Test.Objects.Person, Test.Objects">
|
|
<property name="[0]" value="Master Shake"/>
|
|
<property name="['one']" value="uno"/>
|
|
</object></programlisting></para>
|
|
|
|
<note>The use of the property expression parser in Release 1.0.2
|
|
changed how you configure indexer properties. The following section
|
|
describes this usage. <para> The older style configuration uses the
|
|
following syntax <programlisting><object id="objectWithIndexer" type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="Item[0]" value="my string value"/>
|
|
</object></programlisting> You can also change the name used to identify
|
|
the indexer by adorning your indexer method declaration with the
|
|
attribute <literal>[IndexerName("MyItemName")]</literal>. You would
|
|
then use the string <literal>MyItemName[0]</literal> to configure the
|
|
first element of that indexer. </para> <para>There are some
|
|
limitations to be aware in the older indexer configuration. The
|
|
indexer can only be of a single parameter that is convertible from a
|
|
string to the indexer parameter type. Also, multiple indexers are not
|
|
supported. You can get around that last limitation currently if you
|
|
use the IndexerName attribute. </para></note>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-shortcutforms">
|
|
<title>Value and ref shortcut forms</title>
|
|
|
|
<para>There are also some shortcut forms that are less verbose than
|
|
using the full <literal>value</literal> and <literal>ref</literal>
|
|
elements. The <literal>property</literal>,
|
|
<literal>constructor-arg</literal>, and <literal>entry</literal>
|
|
elements all support a <literal>value</literal> attribute which may be
|
|
used instead of embedding a full <literal>value</literal> element.
|
|
Therefore, the following: <programlisting><property name="myProperty">
|
|
<value>hello</value>
|
|
</property>
|
|
|
|
<constructor-arg>
|
|
<value>hello</value>
|
|
</constructor-arg>
|
|
|
|
<entry key="myKey">
|
|
<value>hello</value>
|
|
</entry></programlisting> are equivalent to:<programlisting><property name="myProperty" value="hello"/>
|
|
|
|
<constructor-arg value="hello"/>
|
|
|
|
<entry key="myKey" value="hello"/></programlisting> In general, when
|
|
typing definitions by hand, you will probably prefer to use the less
|
|
verbose shortcut form.</para>
|
|
|
|
<para>The <literal>property</literal> and
|
|
<literal>constructor-arg</literal> elements support a similar shortcut
|
|
<literal>ref</literal> attribute which may be used instead of a full
|
|
nested <literal>ref</literal> element. Therefore, the following...
|
|
<programlisting><property name="myProperty">
|
|
<ref object="anotherObject"/>
|
|
</property>
|
|
|
|
<constructor-arg index="0">
|
|
<ref object="anotherObject"/>
|
|
</constructor-arg></programlisting> is equivalent to... <programlisting><property name="myProperty" ref="anotherObject"/>
|
|
|
|
<constructor-arg index="0" ref="anotherObject"/></programlisting></para>
|
|
|
|
<note>The shortcut form is equivalent to a <literal><ref
|
|
object="xxx"></literal> element; there is no shortcut for either
|
|
the <literal><ref local="xxx"></literal> or <literal><ref
|
|
parent="xxx"></literal> elements. For a local or parent
|
|
<literal>ref</literal>, you must still use the long form.</note>
|
|
|
|
<para>Finally, the entry element allows a shortcut form the specify
|
|
the key and/or value of a dictionary, in the form of key/key-ref and
|
|
value/value-ref attributes. Therefore, the following <programlisting><entry>
|
|
<key>
|
|
<ref object="MyKeyObject"/>
|
|
</key>
|
|
<ref object="MyValueObject"/>
|
|
</entry></programlisting> Is equivalent to: <programlisting><entry key-ref="MyKeyObject" value-ref="MyValueObject"/></programlisting>
|
|
As mentioned previously, the equivalence is to <literal><ref
|
|
object="xxx"></literal> and not the local or parent forms of object
|
|
references.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-referencing-compound-properties">
|
|
<title>Compound property names and Spring expression
|
|
references</title>
|
|
</sect3>
|
|
|
|
<para>Note that compound or nested property names are perfectly legal
|
|
when setting object properties. Property names are interpreted using the
|
|
<link linkend="expressions">Spring Expression Language</link> (SpEL) and
|
|
therefore can leverage its many features to set property names. For
|
|
example, in this object definition a simple nested property name is
|
|
configured</para>
|
|
|
|
<programlisting><object id="foo" type="Spring.Foo, Spring.Foo">
|
|
<property name="bar.baz.name" value="Bingo"/>
|
|
</object></programlisting>
|
|
|
|
<para>As an example of some alternative ways to declare the property
|
|
name, you can use SpEL's support for indexers to configure a Dictionary
|
|
key value pair as an alternative to the nested
|
|
<literal><dictionary></literal> element. More importantly, you can
|
|
use the 'expression' element to refer to a Spring expression as the
|
|
value of the property. Simple examples of this are shown below</para>
|
|
|
|
<programlisting><property name=“minValue” expression=“int.MinValue” />
|
|
|
|
<property name=“weekFromToday” expression="DateTime.Today + 7"/></programlisting>
|
|
|
|
<para>Using SpEL's support for method evaluation, you can easily call
|
|
static method on various helper classes in your XML
|
|
configuraiton.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-factory-dependson">
|
|
<title>Using <literal>depends-on</literal></title>
|
|
|
|
<para>For most situations, the fact that an object is a dependency of
|
|
another is expressed by the fact that one object is set as a property of
|
|
another. This is typically accomploished with the
|
|
<literal><ref/></literal> element in XML-based configuration
|
|
metadata. For the relatively infrequent situations where dependencies
|
|
between objects are less direct (for example, when a static initializer
|
|
in a class needs to be triggered) the '<literal>depends-on</literal>'
|
|
attribute may be used to explicitly force one or more objects to be
|
|
initialized before the object using this element is initialized. Find
|
|
below an example of using the '<literal>depends-on</literal>' attribute
|
|
to express a dependency on a single object.. <programlisting><object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager">
|
|
<property name="manager" ref="manager"/>
|
|
</object>
|
|
|
|
<object id="manager" type="Examples.ManagerObject, ExamplesLibrary"/></programlisting></para>
|
|
|
|
<para>If you need to express a dependency on multiple objects, you can
|
|
supply a list of object names as the value of the
|
|
'<literal>depends-on</literal>' attribute, with commas, whitespace and
|
|
semicolons all valid delimiters, like so:</para>
|
|
|
|
<programlisting><object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager,accountDao">
|
|
<property name="manager" ref="manager" />
|
|
</object>
|
|
|
|
<object id="manager" type="Examples.ManagerObject, ExamplesLibrary" />
|
|
<object id="accountDao" type="Examples.AdoAccountDao, ExamplesLibrary" /></programlisting>
|
|
|
|
<para><note>
|
|
<para>The '<literal>depends-on</literal>' attribute and property is
|
|
used not only to specify an initialization time dependency, but also
|
|
to specify the corresponding destroy time dependency (in the case of
|
|
singleton objects only). Dependent objects that are defined in the
|
|
'depends-on' attribute will be destroyed after the relevant object
|
|
itself is destroyed. This thus allows you to control shutdown order
|
|
too</para>
|
|
</note></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Lazily-instantiated objects</title>
|
|
|
|
<para>The default behavior for
|
|
<classname>IApplicationContext</classname> implementations is to eagerly
|
|
pre-instantiate all singleton objects at startup. Pre-instantiation
|
|
means that an <classname>IApplicationContext</classname> will eagerly
|
|
create and configure all of its singleton objects as part of its
|
|
initialization process. Generally this is a good thing, because it means
|
|
that any errors in the configuration or in the surrounding environment
|
|
will be discovered immediately (as opposed to possibly hours or even
|
|
days down the line).</para>
|
|
|
|
<para>However, there are times when this behavior is not what is wanted.
|
|
If you do not want a singleton object to be pre-instantiated when using
|
|
an <classname>IApplicationContext</classname>, you can selectively
|
|
control this by marking an object definition as lazy-initialized. A
|
|
lazily-initialized object indicates to the IoC container whether or not
|
|
an object instance should be created at startup or when it is first
|
|
requested.</para>
|
|
|
|
<para>When configuring objects via XML, this lazy loading is controlled
|
|
by the <literal>'lazy-init'</literal>attribute on the
|
|
<literal><object/></literal> element; for example:</para>
|
|
|
|
<programlisting><object id="lazy" type="MyCompany.ExpensiveToCreateObject, MyApp" lazy-init="true"/>
|
|
|
|
<object name="not.lazy" type="MyCompany.AnotherObject, MyApp"/></programlisting>
|
|
|
|
<para>When the above configuration is consumed by an
|
|
<classname>IApplicationContext</classname>, the object named
|
|
<literal>'lazy'</literal> will not be eagerly pre-instantiated when the
|
|
<classname>IApplicationContext</classname> is starting up, whereas the
|
|
'not.lazy' object will be eagerly pre-instantiated.</para>
|
|
|
|
<para>One thing to understand about lazy-initialization is that even
|
|
though an object definition may be marked up as being lazy-initialized,
|
|
if the lazy-initialized object is the dependency of a singleton object
|
|
that is not lazy-initialized, when the
|
|
<classname>IApplicationContext</classname> is eagerly pre-instantiating
|
|
the singleton, it will have to satisfy all of the singletons
|
|
dependencies, one of which will be the lazy-initialized object! So don't
|
|
be confused if the IoC container creates one of the objects that you
|
|
have explicitly configured as lazy-initialized at startup; all that
|
|
means is that the lazy-initialized object is being injected into a
|
|
non-lazy-initialized singleton object elsewhere.</para>
|
|
|
|
<para>It is also possible to control lazy-initialization at the
|
|
container level by using the
|
|
<literal>'default-lazy-init'</literal>attribute on the <objects/>
|
|
element; for example:</para>
|
|
|
|
<programlisting><objects default-lazy-init="true">
|
|
<!-- no objects will be pre-instantiated... -->
|
|
</objects></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-factory-autowire">
|
|
<title>Autowiring collaborators</title>
|
|
|
|
<para>The Spring container is able to autowire relationships between
|
|
collaborating objects. This means that it is possible to automatically
|
|
let Spring resolve collaborators (other objects) for your object by
|
|
inspecting the contents of the IoC container.. The autowiring
|
|
functionality has five modes. Autowiring is specified per object and can
|
|
thus be enabled for some object, while other objects will not be
|
|
autowired. Using autowiring, it is possible to reduce or eliminate the
|
|
need to specify properties or constructor arguments, thus saving a
|
|
significant amount of typing. When using XML-based configuration
|
|
metadata, the autowire mode for an object definition is specified by
|
|
using the autowire attribute of the <object/> element. The
|
|
following values are allowed:</para>
|
|
|
|
<para><table frame="all">
|
|
<title>Autowiring modes</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="1*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Mode</entry>
|
|
|
|
<entry>Explanation</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>no</entry>
|
|
|
|
<entry>No autowiring at all. This is the default value and you
|
|
are encouraged not to change this for large applications,
|
|
since specifying your collaborators explicitly gives you a
|
|
feeling for what you're actually doing (always a bonus) and is
|
|
a great way of somewhat documenting the structure of your
|
|
system.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>byName</entry>
|
|
|
|
<entry>This option will inspect the objects within the
|
|
container, and look for an object named exactly the same as
|
|
the property which needs to be autowired. For example, if you
|
|
have an object definition that is set to autowire by name, and
|
|
it contains a <literal>Master</literal> property, Spring.NET
|
|
will look for an object definition named
|
|
<literal>Master</literal>, and use it as the value of the
|
|
<literal>Master</literal> property on your object
|
|
definition.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>byType</entry>
|
|
|
|
<entry>This option gives you the ability to resolve
|
|
collaborators by type instead of by name. Supposing you have
|
|
an <classname>IObjectDefinition</classname> with a
|
|
collaborator typed <classname>SqlConnection</classname>,
|
|
Spring.NET will search the entire object factory for an object
|
|
definition of type <classname>SqlConnection</classname> and
|
|
use it as the collaborator. <emphasis>If 0 (zero) or more than
|
|
1 (one) object definitions of the desired type exist in the
|
|
container, a failure will be reported and you won't be able to
|
|
use autowiring for that specific object.</emphasis></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>constructor</entry>
|
|
|
|
<entry>This is analogous to <emphasis>byType</emphasis>, but
|
|
applies to constructor arguments. If there isn't exactly one
|
|
object of the constructor argument type in the object factory,
|
|
a fatal error is raised.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>autodetect</entry>
|
|
|
|
<entry>Chooses <emphasis>constructor</emphasis> or
|
|
<emphasis>byType</emphasis> through introspection of the
|
|
object class. If a default constructor is found,
|
|
<emphasis>byType</emphasis> gets applied.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
|
|
<para>Note that explicit dependencies in property and constructor-arg
|
|
settings always override autowiring. Please also note that it is not
|
|
currently possible to autowire so-called simple properties such as
|
|
primitives, Strings, and Types (and arrays of such simple properties).
|
|
(This is by-design and should be considered a feature.) When using
|
|
either the byType or constructor autowiring mode, it is possible to wire
|
|
arrays and typed-collections. In such cases all autowire candidates
|
|
within the container that match the expected type will be provided to
|
|
satisfy the dependency. Strongly-typed IDictionaries can even be
|
|
autowired if the expected key type is string. An autowired IDictionary
|
|
values will consist of all object instances that match the expected
|
|
type, and the IDictionary's keys will contain the corresponding object
|
|
names.</para>
|
|
|
|
<para>Autowire behavior can be combined with dependency checking, which
|
|
will be performed after all autowiring has been completed. It is
|
|
important to understand the various advantages and disadvantages of
|
|
autowiring. Some advantages of autowiring include:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Autowiring can significantly reduce the volume of
|
|
configuration required. However, mechanisms such as the use of a
|
|
object template (discussed elsewhere in this chapter) are also
|
|
valuable in this regard.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Autowiring can cause configuration to keep itself up to date
|
|
as your objects evolve. For example, if you need to add an
|
|
additional dependency to a class, that dependency can be satisfied
|
|
automatically without the need to modify configuration. Thus there
|
|
may be a strong case for autowiring during development, without
|
|
ruling out the option of switching to explicit wiring when the code
|
|
base becomes more stable.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Some disadvantages of autowiring:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Autowiring is more magical than explicit wiring. Although, as
|
|
noted in the above table, Spring is careful to avoid guessing in
|
|
case of ambiguity which might have unexpected results, the
|
|
relationships between your Spring-managed objects are no longer
|
|
documented explicitly.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Wiring information may not be available to tools that may
|
|
generate documentation from a Spring container.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Another issue to consider when autowiring by type is that multiple
|
|
object definitions within the container may match the type specified by
|
|
the setter method or constructor argument to be autowired. For arrays,
|
|
collections, or IDictionary, this is not necessarily a problem. However
|
|
for dependencies that expect a single value, this ambiguity will not be
|
|
arbitrarily resolved. Instead, if no unique object definition is
|
|
available, an Exception will be thrown.</para>
|
|
|
|
<para>When deciding whether to use autowiring, there is no wrong or
|
|
right answer in all cases. A degree of consistency across a project is
|
|
best though; for example, if autowiring is not used in general, it might
|
|
be confusing to developers to use it just to wire one or two object
|
|
definitions.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-factory-dependencies">
|
|
<title>Checking for dependencies</title>
|
|
|
|
<para>Spring.NET has the ability to try to check for the existence of
|
|
unresolved dependencies of an object deployed into the container. These
|
|
are properties of the object, which do not have actual values set for
|
|
them in the object definition, or alternately provided automatically by
|
|
the autowiring feature.</para>
|
|
|
|
<para>This feature is sometimes useful when you want to ensure that all
|
|
properties (or all properties of a certain type) are set on an object.
|
|
Of course, in many cases an object class will have default values for
|
|
many properties, or some properties do not apply to all usage scenarios,
|
|
so this feature is of limited use. Dependency checking can also be
|
|
enabled and disabled per object, just as with the autowiring
|
|
functionality. The default dependency checking mode is to
|
|
<emphasis>not</emphasis> check dependencies. Dependency checking can be
|
|
handled in several different modes. In XML-based configuration, this is
|
|
specified via the <literal>dependency-check</literal> attribute in an
|
|
object definition, which may have the following values. <table
|
|
frame="all">
|
|
<title>Dependency checking modes</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="1*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Mode</entry>
|
|
|
|
<entry>Explanation</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>none</entry>
|
|
|
|
<entry>No dependency checking. Properties of the object which
|
|
have no value specified for them are simply not set.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>simple</entry>
|
|
|
|
<entry>Dependency checking is done for primitive types and
|
|
collections (this means everything except
|
|
collaborators).</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>object</entry>
|
|
|
|
<entry>Dependency checking is done for collaborators
|
|
only.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>all</entry>
|
|
|
|
<entry>Dependency checking is done for collaborators,
|
|
primitive types and collections.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-method-injection">
|
|
<title>Method Injection</title>
|
|
|
|
<para>For most users, the majority of the objects in the container will
|
|
be singletons. When a singleton object needs to collaborate with (use)
|
|
another singleton object, or a non-singleton object needs to collaborate
|
|
with another non-singleton object, the typical and common approach of
|
|
handling this dependency (by defining one object to be a property of the
|
|
other) is quite adequate. There is however a problem when the object
|
|
lifecycles are different. Consider a singleton object A which needs to
|
|
use a non-singleton (prototype) object B, perhaps on each method
|
|
invocation on A. The container will only create the singleton object A
|
|
once, and thus only get the opportunity to set its properties once.
|
|
There is no opportunity for the container to provide object A with a new
|
|
instance of object B every time one is needed.</para>
|
|
|
|
<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">
|
|
<title>Lookup Method Injection</title>
|
|
|
|
<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>
|
|
|
|
<para>Note that lookup method injection can be combined with
|
|
Constructor Injection (supplying optional constructor arguments to the
|
|
object being constructed), and also with Setter Injection (settings
|
|
properties on the object being constructed).</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-method-injection-replacement">
|
|
<title>Arbitrary method replacement</title>
|
|
|
|
<para>A less commonly useful form of method injection than Lookup
|
|
Method Injection is the ability to replace arbitrary methods in a
|
|
managed object with another method implementation. Users may safely
|
|
skip the rest of this section (which describes this somewhat advanced
|
|
feature), until this functionality is actually needed.</para>
|
|
|
|
<para>In an <classname>XmlObjectFactory</classname>, the
|
|
<literal>replaced-method</literal> element may be used to replace an
|
|
existing method implementation with another. Consider the following
|
|
class, with a method <literal>ComputeValue</literal>, which we want to
|
|
override:</para>
|
|
|
|
<programlisting>public class MyValueCalculator {
|
|
|
|
public virtual string ComputeValue(string input) {
|
|
// ... some real code
|
|
}
|
|
|
|
// ... some other methods
|
|
}</programlisting>
|
|
|
|
<para>A class implementing the
|
|
<classname>Spring.Objects.Factory.Support.IMethodReplacer</classname>
|
|
interface is needed to provide the new (injected) method
|
|
definition.</para>
|
|
|
|
<programlisting>/// <summary>
|
|
/// Meant to be used to override the existing ComputeValue(string)
|
|
/// implementation in MyValueCalculator.
|
|
/// </summary>
|
|
public class ReplacementComputeValue : IMethodReplacer
|
|
{
|
|
public object Implement(object target, MethodInfo method, object[] arguments)
|
|
{
|
|
// get the input value, work with it, and return a computed result...
|
|
string value = (string) arguments[0];
|
|
// compute...
|
|
return result;
|
|
}
|
|
}</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">
|
|
<!-- arbitrary method replacement -->
|
|
<replaced-method name="ComputeValue" replacer="replacementComputeValue">
|
|
<arg-type match="String"/>
|
|
</replaced-method>
|
|
</object>
|
|
|
|
<object id="replacementComputeValue" type="Examples.ReplacementComputeValue, ExampleAssembly"/></programlisting>
|
|
|
|
<para>One or more contained <literal>arg-type</literal> elements
|
|
within the <literal>replaced-method</literal> element may be used to
|
|
indicate the method signature of the method being overridden. Note
|
|
that the signature for the arguments is actually only needed in the
|
|
case that the method is actually overloaded and there are multiple
|
|
variants within the class. For convenience, the type string for an
|
|
argument may be a substring of the fully qualified type name. For
|
|
example, all the following would match
|
|
<classname>System.String</classname>.</para>
|
|
|
|
<programlisting> System.String
|
|
String
|
|
Str</programlisting>
|
|
|
|
<para>Since the number of arguments is often enough to distinguish
|
|
between each possible choice, this shortcut can save a lot of typing,
|
|
by just using the shortest string which will match an argument.</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-advancedproperty-setting">
|
|
<title>Setting a reference using the members of other objects and
|
|
classes.</title>
|
|
|
|
<para>This section details those configuration scenarios that involve
|
|
the setting of properties and constructor arguments using the members of
|
|
other objects and classes. This kind of scenario is quite common,
|
|
especially when dealing with legacy classes that you cannot (or won't)
|
|
change to accommodate some of Spring.NET's conventions... consider the
|
|
case of a class that has a constructor argument that can only be
|
|
calculated by going to say, a database. The
|
|
<classname>MethodInvokingFactoryObject</classname> handles exactly this
|
|
scenario ... it will allow you to inject the result of an arbitrary
|
|
method invocation into a constructor (as an argument) or as the value of
|
|
a property setter. Similarly,
|
|
<classname>PropertyRetrievingFactoryObject</classname> and
|
|
<classname>FieldRetrievingFactoryObject</classname> allow you to
|
|
retrieve values from another object's property or field value. These
|
|
classes implement the <classname>IFactoryObject</classname> interface
|
|
which indicates to Spring.NET that this object is itself a factory and
|
|
the factories product, not the factory itself, is what will be
|
|
associated with the object id. Factory objects are discussed further in
|
|
<xref linkend="objects-factory-lifecycle-factoryobject" /></para>
|
|
|
|
<sect3>
|
|
<title>Setting a reference to the value of property.</title>
|
|
|
|
<para>The <classname>PropertyRetrievingFactoryObject</classname> is an
|
|
<classname>IFactoryObject</classname> that addresses the scenario of
|
|
setting one of the properties and / or constructor arguments of an
|
|
object to the value of a property exposed on another object or class.
|
|
One can use it to get the value of any <emphasis
|
|
role="bold">public</emphasis> property exposed on either an instance
|
|
or a class (in the case of a property exposed on a class, the property
|
|
must obviously be static).</para>
|
|
|
|
<para>In the case of a property exposed on an instance, the target
|
|
object that a <classname>PropertyRetrievingFactoryObject</classname>
|
|
will evaluate can be either an object instance specified directly
|
|
inline or a reference to another arbitrary object. In the case of a
|
|
static property exposed on a class, the target object will be the
|
|
class (the .NET <classname>System.Type</classname>) exposing the
|
|
property.</para>
|
|
|
|
<para>The result of evaluating the property lookup may then be used in
|
|
another object definition as a property value or constructor argument.
|
|
Note that nested properties are supported for both instance and class
|
|
property lookups. The <classname>IFactoryObject</classname> is
|
|
discussed more generally in <xref
|
|
linkend="objects-factory-lifecycle-factoryobject" />.</para>
|
|
|
|
<para>Here's an example where a property path is used against another
|
|
object instance. In this case, an inner object definition is used and
|
|
the property path is nested, i.e. spouse.age. <programlisting><object name="person" type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="age" value="20"/>
|
|
<property name="spouse">
|
|
<object type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="age" value="21"/>
|
|
</object>
|
|
</property>
|
|
</object>
|
|
|
|
// will result in 21, which is the value of property 'spouse.age' of object 'person'
|
|
<object name="theAge" type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="person"/>
|
|
<property name="TargetProperty" value="spouse.age"/>
|
|
</object></programlisting></para>
|
|
|
|
<para>An example of using a
|
|
<classname>PropertyRetrievingFactoryObject</classname> to evaluate a
|
|
<literal>static</literal> property is shown below.</para>
|
|
|
|
<programlisting><object id="cultureAware"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
|
|
<property name="culture" ref="cultureFactory"/>
|
|
</object>
|
|
|
|
<object id="cultureFactory"
|
|
type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
|
|
<property name="StaticProperty">
|
|
<value>System.Globalization.CultureInfo.CurrentUICulture, Mscorlib</value>
|
|
</property>
|
|
</object></programlisting>
|
|
|
|
<para>Similarly, an example showing the use of an instance property is
|
|
shown below.</para>
|
|
|
|
<programlisting><object id="instancePropertyCultureAware"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
|
|
<property name="Culture" ref="instancePropertyCultureFactory"/>
|
|
</object>
|
|
|
|
<object id="instancePropertyCultureFactory"
|
|
type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="instancePropertyCultureAwareSource"/>
|
|
<property name="TargetProperty" value="MyDefaultCulture"/>
|
|
</object>
|
|
|
|
<object id="instancePropertyCultureAwareSource"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/>
|
|
</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Setting a reference to the value of field.</title>
|
|
|
|
<para>The <classname>FieldRetrievingFactoryObject</classname> class
|
|
addresses much the same area of concern as the
|
|
<classname>PropertyRetrievingFactoryObject</classname> described in
|
|
the previous section. However, as its name might suggest, the
|
|
<classname>FieldRetrievingFactoryObject</classname> class is concerned
|
|
with looking up the value of a <emphasis role="bold">public</emphasis>
|
|
field exposed on either an instance or a class (and similarly, in the
|
|
case of a field exposed on a class, the field must obviously be
|
|
static).</para>
|
|
|
|
<para>The following example demonstrates using a
|
|
<classname>FieldRetrievingFactoryObject</classname> to look up the
|
|
value of a (public, static) field exposed on a class</para>
|
|
|
|
<para><programlisting><object id="withTypesField"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
|
|
<property name="Types" ref="emptyTypesFactory"/>
|
|
</object>
|
|
|
|
<object id="emptyTypesFactory"
|
|
type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core">
|
|
<property name="TargetType" value="System.Type, Mscorlib"/>
|
|
<property name="TargetField" value="EmPTytypeS"/>
|
|
</object>
|
|
</programlisting></para>
|
|
|
|
<para>The example in the next section demonstrates the look up of a
|
|
(public) field exposed on an object instance.</para>
|
|
|
|
<programlisting><object id="instanceCultureAware"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
|
|
<property name="Culture" ref="instanceCultureFactory"/>
|
|
</object>
|
|
|
|
<object id="instanceCultureFactory"
|
|
type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="instanceCultureAwareSource"/>
|
|
<property name="TargetField" value="Default"/>
|
|
</object>
|
|
|
|
<object id="instanceCultureAwareSource"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/>
|
|
</programlisting>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-methodfactory">
|
|
<title>Setting a property or constructor argument to the return value
|
|
of a method invocation.</title>
|
|
|
|
<para>The <classname>MethodInvokingFactoryObject</classname> rounds
|
|
out the trio of classes that permit the setting of properties and
|
|
constructor arguments using the members of other objects and classes.
|
|
Whereas the <classname>PropertyRetrievingFactoryObject</classname> and
|
|
<classname>FieldRetrievingFactoryObject</classname> classes dealt with
|
|
simply looking up and returning the value of property or field on an
|
|
object or class, the
|
|
<classname>MethodInvokingFactoryObject</classname> allows one to set a
|
|
constructor or property to the return value of an arbitrary method
|
|
invocation,</para>
|
|
|
|
<para>The <classname>MethodInvokingFactoryObject</classname> class
|
|
handles both the case of invoking an (instance) method on another
|
|
object in the container, and the case of a static method call on an
|
|
arbitrary class. Additionally, it is sometimes necessary to invoke a
|
|
method just to perform some sort of initialization.... while the
|
|
mechanisms for handling object initialization have yet to be
|
|
introduced (see <xref
|
|
linkend="objects-factory-lifecycle-initializingobject" />), these
|
|
mechanisms do not permit any arguments to be passed to any
|
|
initialization method, and are confined to invoking an initialization
|
|
method on the object that has just been instantiated by the container.
|
|
The <classname>MethodInvokingFactoryObject</classname> allows one to
|
|
invoke pretty much <emphasis role="bold">any</emphasis> method on any
|
|
object (or class in the case of a static method).</para>
|
|
|
|
<para>The following example (in an XML based
|
|
<classname>IObjectFactory</classname> definition) uses the
|
|
<classname>MethodInvokingFactoryObject</classname> class to force a
|
|
call to a static factory method prior to the instantiation of the
|
|
object...</para>
|
|
|
|
<para><programlisting><object id="force-init"
|
|
type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="StaticMethod">
|
|
<value>ExampleNamespace.ExampleInitializerClass.Initialize</value>
|
|
</property>
|
|
</object>
|
|
<object id="myService" depends-on="force-init"/></programlisting> Note
|
|
that the definition for the <literal>myService</literal> object has
|
|
used the <literal>depends-on</literal> attribute to refer to the
|
|
<literal>force-init</literal> object, which will force the
|
|
initialization of the <literal>force-init</literal> object first (and
|
|
thus the calling of its configured <literal>StaticMethod</literal>
|
|
static initializer method, when <literal>myService</literal> is first
|
|
initialized. Please note that in order to effect this initialization,
|
|
the <classname>MethodInvokingFactoryObject</classname> object
|
|
<emphasis role="bold">must</emphasis> be operating in
|
|
<literal>singleton</literal> mode (the default.. see the next
|
|
paragraph).</para>
|
|
|
|
<para>Note that since this class is expected to be used primarily for
|
|
accessing factory methods, this factory defaults to operating in
|
|
<literal>singleton</literal> mode. As such, as soon as all of the
|
|
properties for a <classname>MethodInvokingFactoryObject</classname>
|
|
object have been set, and if the
|
|
<classname>MethodInvokingFactoryObject</classname> object is still in
|
|
<literal>singleton</literal> mode, the method will be invoked
|
|
immediately and the return value cached for later access. The first
|
|
request by the container for the factory to produce an object will
|
|
cause the factory to return the cached return value for the current
|
|
request (and all subsequent requests). The
|
|
<methodname>IsSingleton</methodname> property may be set to false, to
|
|
cause this factory to invoke the target method each time it is asked
|
|
for an object (in this case there is obviously no caching of the
|
|
return value).</para>
|
|
|
|
<para>A static target method may be specified by setting the
|
|
<methodname>targetMethod</methodname> property to a string
|
|
representing the static method name, with
|
|
<methodname>TargetType</methodname> specifying the
|
|
<classname>Type</classname> that the static method is defined on.
|
|
Alternatively, a target instance method may be specified, by setting
|
|
the <methodname>TargetObject</methodname> property to the name of
|
|
another Spring.NET managed object definition (the target object), and
|
|
the <methodname>TargetMethod</methodname> property to the name of the
|
|
method to call on that target object.</para>
|
|
|
|
<para>Arguments for the method invocation may be specified in two ways
|
|
(or even a mixture of both)... the first involves setting the
|
|
<methodname>Arguments</methodname> property to the list of arguments
|
|
for the method that is to be invoked. Note that the ordering of these
|
|
arguments is significant... the order of the values passed to the
|
|
<methodname>Arguments</methodname> property must be the same as the
|
|
order of the arguments defined on the method signature, including the
|
|
argument <classname>Type</classname>. This is shown in the example
|
|
below <programlisting><object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="TargetType" value="Whatever.MyClassFactory, MyAssembly"/>
|
|
<property name="TargetMethod" value="GetInstance"/>
|
|
|
|
<!-- the ordering of arguments is significant -->
|
|
<property name="Arguments">
|
|
<list>
|
|
<value>1st</value>
|
|
<value>2nd</value>
|
|
<value>and 3rd arguments</value>
|
|
<!-- automatic Type-conversion will be performed prior to invoking the method -->
|
|
</list>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<para>The second way involves passing an arguments dictionary to the
|
|
<methodname>NamedArguments</methodname> property... this dictionary
|
|
maps argument names (<classname>String</classname>s) to argument
|
|
values (any object). The argument names are not case-sensitive, and
|
|
order is (obviously) not significant (since dictionaries by definition
|
|
do not have an order). This is shown in the example below
|
|
<programlisting><object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="TargetObject">
|
|
<object type="Whatever.MyClassFactory, MyAssembly"/>
|
|
</property>
|
|
<property name="TargetMethod" value="Execute"/>
|
|
|
|
<!-- the ordering of named arguments is not significant -->
|
|
<property name="NamedArguments">
|
|
<dictionary>
|
|
<entry key="argumentName"><value>1st</value></entry>
|
|
<entry key="finalArgumentName"><value>and 3rd arguments</value></entry>
|
|
<entry key="anotherArgumentName"><value>2nd</value></entry>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<para>The following example shows how use
|
|
<classname>MethodInvokingFactoryObject</classname> to call an instance
|
|
method.<programlisting><object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />
|
|
|
|
<object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="myMethodObject"/>
|
|
<property name="TargetMethod" value="Execute"/>
|
|
</object></programlisting> The above example could also have been
|
|
written using an anonymous inner object definition... if the object on
|
|
which the method is to be invoked is not going to be used outside of
|
|
the factory object definition, then this is the preferred idiom
|
|
because it limits the scope of the object on which the method is to be
|
|
invoked to the surrounding factory object.</para>
|
|
|
|
<para>Finally, if you want to use
|
|
<classname>MethodInvokingFactoryObject</classname> in conjunction with
|
|
a method that has a variable length argument list, then please note
|
|
that the variable arguments need to be passed (and configured) as a
|
|
<emphasis>list</emphasis>. Let us consider the following method
|
|
definition that uses the <classname>params</classname> keyword (in
|
|
C#), and its attendant (XML) configuration... <programlisting>[C#]
|
|
public class MyClassFactory
|
|
{
|
|
public object CreateObject(Type objectType, params string[] arguments)
|
|
{
|
|
return ... // implementation elided for clarity...
|
|
}
|
|
}</programlisting> <programlisting><object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />
|
|
|
|
<object id="paramsMethodObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="myMethodObject"/>
|
|
<property name="TargetMethod" value="CreateObject"/>
|
|
<property name="Arguments">
|
|
<list>
|
|
<value>System.String</value>
|
|
<!-- here is the 'params string[] arguments' -->
|
|
<list>
|
|
<value>1st</value>
|
|
<value>2nd</value>
|
|
</list>
|
|
</list>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-objectfactories">
|
|
<title>Provided IFactoryObject implementations</title>
|
|
|
|
<para>In addition to
|
|
<classname>PropertyRetrievingFactoryObject</classname>,
|
|
<classname>MethodInvokingFactoryObject</classname>, and
|
|
<classname>FieldRetrievingFactoryObject </classname> Spring.NET comes
|
|
with other useful implementations of the
|
|
<classname>IFactoryObject</classname> interface. These are discussed
|
|
below.</para>
|
|
|
|
<sect3 id="objects-objectfactories-log4net">
|
|
<title>Common logging</title>
|
|
|
|
<para>The <classname>LogFactoryObject</classname> is useful when you
|
|
would like to share a Common.Logging log object across a number of
|
|
classes instead of creating a logging instance per class or class
|
|
hierarchy. Information on the Common.Logging project can be found
|
|
<ulink url="http://netcommon.sourceforge.net/">here</ulink>. In the
|
|
example shown below the same logging instance, with a logging category
|
|
name of "DAOLogger", is used in both the SimpleAccountDao and
|
|
SimpleProductDao data access objects. <programlisting><objects xmlns="http://www.springframework.net"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.springframework.net
|
|
http://www.springframework.net/xsd/spring-objects.xsd" >
|
|
|
|
<object name="daoLogger" type="Spring.Objects.Factory.Config.LogFactoryObject, Spring.Core">
|
|
<property name="logName" value="DAOLogger"/>
|
|
</object>
|
|
|
|
<object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp ">
|
|
<property name="maxResults" value="100"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
<property name="log" ref="daoLogger"/>
|
|
</object>
|
|
|
|
<object name="accountDao" type="PropPlayApp.SimpleAccountDao, PropPlayApp ">
|
|
<property name="maxResults" value="100"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
<property name="log" ref="daoLogger"/>
|
|
</object>
|
|
|
|
<object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data">
|
|
<property name="connectionstring" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/>
|
|
</object>
|
|
|
|
</objects></programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Object Scopes</title>
|
|
|
|
<para>When you create a object definition what you are actually creating
|
|
is a recipe for creating actual instances of the class defined by that
|
|
object definition. The idea that a object definition is a recipe is
|
|
important, because it means that, just like a class, you can potentially
|
|
have many object instances created from a single recipe.</para>
|
|
|
|
<para>You can control not only the various dependencies and configuration
|
|
values that are to be plugged into an object that is created from a
|
|
particular object definition, but also the scope of the objects created
|
|
from a particular object definition. This approach is very powerful and
|
|
gives you the flexibility to choose the scope of the objects you create
|
|
through configuration instead of having to 'bake in' the scope of an
|
|
object at the .NET class level. Objects can be defined to be deployed in
|
|
one of a number of scopes: out of the box, the Spring Framework supports
|
|
exactly five scopes (of which three are available only if you are using a
|
|
web-aware ApplicationContext).</para>
|
|
|
|
<para>The scopes supported out of the box are listed below:</para>
|
|
|
|
<table frame="all">
|
|
<title>Object Scopes</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="2*" />
|
|
|
|
<colspec colname="c2" colwidth="4*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Scope</entry>
|
|
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>singleton</entry>
|
|
|
|
<entry>Scopes a single object definition to a single object
|
|
instance per Spring IoC container.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>prototype</entry>
|
|
|
|
<entry>Scopes a single object definition to any number of object
|
|
instances.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>request</entry>
|
|
|
|
<entry>Scopes a single object definition to the lifecycle of a
|
|
single HTTP request; that is each and every HTTP request will have
|
|
its own instance of an object created off the back of a single
|
|
object definition. Only valid in the context of a web-aware Spring
|
|
ApplicationContext.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>session</entry>
|
|
|
|
<entry>Scopes a single object definition to the lifecycle of a
|
|
HTTP Session. Only valid in the context of a web-aware Spring
|
|
ApplicationContext.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>application</entry>
|
|
|
|
<entry>Scopes a single object definition to the lifecycle of a web
|
|
application. Only valid in the context of a web-aware Spring
|
|
ApplicationContext.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<sect2 id="objects-factory-scopes-singleton">
|
|
<title>The singleton scope</title>
|
|
|
|
<para>When an object is a singleton, only one shared instance of the
|
|
object will be managed, and all requests for objects with an id or ids
|
|
matching that object definition will result in that one specific object
|
|
instance being returned by the Spring container.</para>
|
|
|
|
<para>To put it another way, when you define an object definition and it
|
|
is scoped as a singleton, then the Spring IoC container will create
|
|
exactly one instance of the object defined by that object definition.
|
|
This single instance will be stored in a cache of such singleton object,
|
|
and all subsequent requests and references for that named object will
|
|
result in the cached object being returned.</para>
|
|
|
|
<para>Please be aware that Spring's concept of a singleton object is
|
|
quite different from the Singleton pattern as defined in the seminal
|
|
Gang of Four (GoF) patterns book. The GoF Singleton hard codes the scope
|
|
of an object such that one and only one instance of a particular class
|
|
will ever be created per ApplicationDomain. The scope of the Spring
|
|
singleton is best described as per container and per object. This means
|
|
that if you define one object for a particular class in a single Spring
|
|
container, then the Spring container will create one and only one
|
|
instance of the class defined by that object definition. The singleton
|
|
scope is the default scope in Spring. To define an object as a singleton
|
|
in XML, you would write configuration like so:</para>
|
|
|
|
<programlisting><object id="accountService" type="MyApp.DefaultAccountService, MyApp"/>
|
|
|
|
<!-- the following is equivalent, though redundant (singleton scope is the default) -->
|
|
<object id="accountService" type="MyApp.DefaultAccountService, MyApp" singleton="true"/>
|
|
|
|
</programlisting>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-factory-scopes-prototype">
|
|
<title>The prototype scope</title>
|
|
|
|
<para>The non-singleton, prototype scope of object deployment results in
|
|
the creation of a new object instance every time a request for that
|
|
specific object is made (that is, it is injected into another object or
|
|
it is requested via a programmatic GetObject() method call on the
|
|
container). As a rule of thumb, you should use the prototype scope for
|
|
all objects that are stateful, while the singleton scope should be used
|
|
for stateless objects.</para>
|
|
|
|
<para>To define an object as a prototype in XML, you would write
|
|
configuration like so:</para>
|
|
|
|
<programlisting><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary" singleton="false"/></programlisting>
|
|
|
|
<para>There is one quite important thing to be aware of when deploying
|
|
an object in the prototype scope, in that the lifecycle of the object
|
|
changes slightly. Spring does not manage the complete lifecycle of a
|
|
prototype object: the container instantiates, configures, decorates and
|
|
otherwise assembles a prototype object, hands it to the client and then
|
|
has no further knowledge of that prototype instance. This means that
|
|
while <emphasis>initialization</emphasis> lifecycle callback methods
|
|
will be called on all objects regardless of scope, in the case of
|
|
prototypes, any configured <emphasis>destruction</emphasis> lifecycle
|
|
callbacks will <emphasis>not</emphasis> be called. It is the
|
|
responsibility of the client code to clean up prototype scoped objects
|
|
and release any expensive resources that the prototype object(s) are
|
|
holding onto. (One possible way to get the Spring container to release
|
|
resources used by singleton-scoped objects is through the use of a
|
|
custom object post processor which would hold a reference to the objects
|
|
that need to be cleaned up.)</para>
|
|
|
|
<para>In some respects, you can think of the Spring containers role when
|
|
talking about a prototype-scoped object as somewhat of a replacement for
|
|
the C# 'new' operator. All lifecycle aspects past that point have to be
|
|
handled by the client. (The lifecycle of a object in the Spring
|
|
container is further described in the section entitled “Lifecycle
|
|
callbacks”.)</para>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-factory-scopes-sing-prot-interaction">
|
|
<title>Singleton objecgts with prototype-object dependencies</title>
|
|
|
|
<para>When using singleton-scoped objects that have dependencies on
|
|
objects that are scoped as prototypes, please be aware that dependencies
|
|
are resolved at instantiation time. This means that if you dependency
|
|
inject a prototype-scoped object into a singleton-scoped object, a brand
|
|
new prototype object will be instantiated and then dependency injected
|
|
into the singleton object... but that is all. That exact same prototype
|
|
instance will be the sole instance that is ever supplied to the
|
|
singleton-scoped object, which is fine if that is what you want.</para>
|
|
|
|
<para>However, sometimes what you actually want is for the
|
|
singleton-scoped object to be able to acquire a brand new instance of
|
|
the prototype-scoped object again and again and again at runtime. In
|
|
that case it is no use just dependency injecting a prototype-scoped
|
|
object into your singleton object, because as explained above, that only
|
|
happens once when the Spring container is instantiating the singleton
|
|
object and resolving and injecting its dependencies. If you are in the
|
|
scenario where you need to get a brand new instance of a (prototype)
|
|
object again and again and again at runtime, you are referred to the
|
|
section entitled “Method Injection”.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>The other scopes</title>
|
|
|
|
<para>The other scopes, namely request, session, and application are for
|
|
use only in web-based applications. Please refer to the <link
|
|
linkend="web-objectscope">web documentation on object scopes</link> for
|
|
more information.</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="objects-type-conversion">
|
|
<title>Type conversion</title>
|
|
|
|
<para>Type converters are responsible for converting objects from one type
|
|
to another. When using the XML based file to configure the IoC container,
|
|
string based property values are converted to the target property type.
|
|
Spring will rely on the standard .NET support for type conversion unless
|
|
an alternative <classname>TypeConverter</classname> is registered for a
|
|
given type. How to register custom TypeConverters will be described
|
|
shortly. As a reminder, the standard .NET type converter support works by
|
|
associating a <classname>TypeConverter</classname> attribute with the
|
|
class definition by passing the type of the converter as an attribute
|
|
argument. <footnote>
|
|
<para>More information about creating custom
|
|
<literal>TypeConverter</literal> implementations can be found online
|
|
at Microsoft's MSDN website, by searching for <emphasis>Implementing a
|
|
Type Converter</emphasis>.</para>
|
|
</footnote> For example, an abbreviated class definition for the BCL
|
|
type <classname>Font</classname> is shown below. <programlisting>[Serializable, TypeConverter(typeof(FontConverter)), ...]
|
|
public sealed class Font : MarshalByRefObject, ICloneable, ISerializable, IDisposable
|
|
{
|
|
// Methods
|
|
|
|
... etc ..
|
|
}</programlisting></para>
|
|
|
|
<sect2 id="objects-type-conversion-enums">
|
|
<title>Type Conversion for Enumerations</title>
|
|
|
|
<para>The default type converter for enumerations is the
|
|
<classname>System.ComponentModel.EnumConverter</classname> class. To
|
|
specify the value for an enumerated property, simply use the name of the
|
|
property. For example the <classname>TestObject</classname> class has a
|
|
property of the enumerated type <classname>FileMode</classname>. One of
|
|
the values for this enumeration is named <literal>Create</literal>. The
|
|
following XML fragment shows how to configure this property</para>
|
|
|
|
<programlisting><object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="name" value="Rod"/>
|
|
<property name="FileMode" value="Create"/>
|
|
</object></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-type-conversion-builtin">
|
|
<title>Built-in TypeConverters</title>
|
|
|
|
<para>Spring.NET pre-registers a number of custom
|
|
<classname>TypeConverter</classname> instances (for example, to convert
|
|
a type expressed as a string into a real
|
|
<classname>System.Type</classname> object). Each of those is listed
|
|
below and they are all located in the
|
|
<literal>Spring.Objects.TypeConverters</literal> namespace of the
|
|
<literal>Spring.Core</literal> library.</para>
|
|
|
|
<para><table frame="all">
|
|
<title>Built-in <classname>TypeConverters</classname></title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="3*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Type</entry>
|
|
|
|
<entry>Explanation</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><literal>RuntimeTypeConverter</literal></entry>
|
|
|
|
<entry>Parses strings representing
|
|
<classname>System.Types</classname> to actual
|
|
<classname>System.Types</classname> and the other way
|
|
around.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>FileInfoConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving strings to a
|
|
<classname>System.IO.FileInfo</classname> object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>StringArrayConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a comma-delimited list of strings
|
|
to a string-array and vice versa.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>UriConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string representation of a Uri
|
|
to an actual <literal>Uri</literal>-object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>CredentialConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string representation of a
|
|
credential for Web client authentication into an instance of
|
|
<literal>System.Net.ICredentials</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>StreamConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving Spring IResource Uri (string) to
|
|
its corresponding
|
|
<literal>InputStream</literal>-object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>ResourceConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving Spring IResource Uri (string) to
|
|
an <literal>IResource</literal> object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>ResourceManagerConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a two part string (resource name,
|
|
assembly name) to a
|
|
<classname>System.Resources.ResourceManager</classname>
|
|
object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>RgbColorConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a comma separated list of Red,
|
|
Green, Blue integer values to a
|
|
<classname>System.Drawing.Color</classname> structure.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>ExpressionConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string into an instance of an
|
|
object that implements the <classname>IExpression</classname>
|
|
interface.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>NameValueConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving an XML formatted string to a
|
|
<literal>Specialized.NameValueCollection</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>RegexConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string into an instance of
|
|
<literal>Regex</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>RegistryKeyConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string into a
|
|
<literal>Microsoft.Win32.RegistryKey</literal> object.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
|
|
<para>Spring.NET uses the standard .NET mechanisms for the resolution of
|
|
<classname>System.Types</classname>, including, but not limited to
|
|
checking any configuration files associated with your application,
|
|
checking the Global Assembly Cache (GAC), and assembly probing.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-type-conversion-custom-overview">
|
|
<title>Custom Type Conversion</title>
|
|
|
|
<para>There are a few ways to register custom type converters. The
|
|
fundamental storage area in Spring for custom type converters is the
|
|
<classname>TypeConverterRegistry</classname> class. The <emphasis>most
|
|
convenient way</emphasis> if using an XML based implementation of
|
|
<classname>IObjectFactory</classname> or
|
|
<classname>IApplicationContext</classname> is to use the custom
|
|
configuration section handler
|
|
<classname>TypeConverterSectionHandler</classname> This is demonstrated
|
|
in section <xref linkend="context-configuration" /></para>
|
|
|
|
<para>An alternate approach, present for legacy reasons in the port of
|
|
Spring.NET from the Java code base, is to use the object factory
|
|
post-processor
|
|
<classname>Spring.Objects.Factory.Config.CustomConverterConfigurer</classname>.
|
|
This is described in the next section.</para>
|
|
|
|
<para>If you are constructing your IoC container Programatically then
|
|
you should use the <literal>RegisterCustomConverter(Type requiredType,
|
|
TypeConverter converter)</literal> method of the
|
|
<literal>ConfigurableObjectFactory</literal> interface.</para>
|
|
|
|
<sect3 id="objects-type-conversion-customconverter">
|
|
<title>Using CustomConverterConfigurer</title>
|
|
|
|
<para>This section shows in detail how to define a custom type
|
|
converter that does not use the .NET
|
|
<classname>TypeConverter</classname> attribute. The type converter
|
|
class is standalone and inherits from the
|
|
<classname>TypeConverter</classname> class. It uses the legacy factory
|
|
post-processor approach.</para>
|
|
|
|
<para>Consider a user class <emphasis>ExoticType</emphasis>, and
|
|
another class <emphasis>DependsOnExoticType</emphasis> which needs
|
|
ExoticType set as a property:<programlisting>public class ExoticType
|
|
{
|
|
private string name;
|
|
|
|
public ExoticType(string name)
|
|
{
|
|
this.name = name;
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get { return this.name; }
|
|
}
|
|
}</programlisting> and <programlisting>public class DependsOnExoticType
|
|
{
|
|
public DependsOnExoticType() {}
|
|
|
|
private ExoticType exoticType;
|
|
|
|
public ExoticType ExoticType
|
|
{
|
|
get { return this.exoticType; }
|
|
set { this.exoticType = value; }
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return exoticType.Name;
|
|
}
|
|
}</programlisting> When things are properly set up, we want to be able to
|
|
assign the type property as a string, which a TypeConverter will
|
|
convert into a real ExoticType object behind the scenes:
|
|
<programlisting><object name="sample" type="SimpleApp.DependsOnExoticType, SimpleApp">
|
|
<property name="exoticType" value="aNameForExoticType"/>
|
|
</object></programlisting> The TypeConverter looks like this:
|
|
<programlisting>public class ExoticTypeConverter : TypeConverter
|
|
{
|
|
public ExoticTypeConverter()
|
|
{
|
|
}
|
|
|
|
public override bool CanConvertFrom (
|
|
ITypeDescriptorContext context,
|
|
Type sourceType)
|
|
{
|
|
if (sourceType == typeof (string))
|
|
{
|
|
return true;
|
|
}
|
|
return base.CanConvertFrom (context, sourceType);
|
|
}
|
|
|
|
public override object ConvertFrom (
|
|
ITypeDescriptorContext context,
|
|
CultureInfo culture, object value)
|
|
{
|
|
string s = value as string;
|
|
if (s != null)
|
|
{
|
|
return new ExoticType(s.ToUpper());
|
|
}
|
|
return base.ConvertFrom (context, culture, value);
|
|
}
|
|
}</programlisting> Finally, we use the
|
|
<classname>CustomConverterConfigurer</classname> to register the new
|
|
<classname>TypeConverter</classname> with the
|
|
<classname>IApplicationContext</classname>, which will then be able to
|
|
use it as needed: <programlisting><object id="customConverterConfigurer"
|
|
type="Spring.Objects.Factory.Config.CustomConverterConfigurer, Spring.Core">
|
|
<property name="CustomConverters">
|
|
<dictionary>
|
|
<entry key="SimpleApp.ExoticType">
|
|
<object type="SimpleApp.ExoticTypeConverter"/>
|
|
</entry>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="objects-factory-nature">
|
|
<title>Customizing the nature of an object</title>
|
|
|
|
<sect2 id="objects-factory-lifecycle">
|
|
<title>Lifecycle interfaces</title>
|
|
|
|
<para>Spring.NET uses several marker interfaces to change the behaviour
|
|
of your object in the container, namely the Spring.NET specific
|
|
<literal>IInitializingObject</literal> interface and the standard
|
|
<literal>System.IDisposable</literal> interfaces. Implementing either of
|
|
the aforementioned interfaces will result in the container calling the
|
|
<literal>AfterPropertiesSet()</literal> method for the former and the
|
|
<literal>Dispose()</literal> method for the latter, thus allowing you to
|
|
do things upon the initialization and destruction of your
|
|
objects.</para>
|
|
|
|
<para>Internally, Spring.NET uses implementations of the
|
|
<classname>IObjectPostProcessor</classname> interface to process any
|
|
marker interfaces it can find and call the appropriate methods. If you
|
|
need custom features or other lifecycle behavior Spring.NET doesn't
|
|
offer out-of-the-box, you can implement an
|
|
<classname>IObjectPostProcessor</classname> yourself. More information
|
|
about this can be found in <xref
|
|
linkend="objects-factory-customizing" />.</para>
|
|
|
|
<para>All the different lifecycle marker interfaces are described
|
|
below.</para>
|
|
|
|
<sect3 id="objects-factory-lifecycle-initializingobject">
|
|
<title>IInitializingObject / <literal>init-method</literal></title>
|
|
|
|
<para>The
|
|
<classname>Spring.Objects.Factory.IInitializingObject</classname>
|
|
interface gives you the ability to perform initialization work after
|
|
all the necessary properties on an object are set by the container.
|
|
The <classname>IInitializingObject</classname> interface specifies
|
|
exactly one method: <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><methodname>void AfterPropertiesSet()</methodname>: called
|
|
after all properties have been set by the container. This method
|
|
enables you to do checking to see if all necessary properties
|
|
have been set correctly, or to perform further initialization
|
|
work. You can throw <emphasis>any</emphasis>
|
|
<classname>Exception</classname> to indicate misconfiguration,
|
|
initialization failures, etc.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<note>
|
|
Generally, the use of the
|
|
|
|
<classname>IInitializingObject</classname>
|
|
|
|
can be avoided. The
|
|
|
|
<literal>Spring.Core</literal>
|
|
|
|
library provides support for a generic init-method, given to the object definition in the object configuration store (be it XML, or a database, etc).
|
|
</note>
|
|
|
|
<para><programlisting><object id="exampleInitObject" type="Examples.ExampleObject" init-method="init"/>
|
|
[C#]
|
|
public class ExampleObject
|
|
{
|
|
public void Init()
|
|
{
|
|
// do some initialization work
|
|
}
|
|
}</programlisting> Is exactly the same as... <programlisting><object id="exampleInitObject" type="Examples.AnotherExampleObject"/>
|
|
[C#]
|
|
public class AnotherExampleObject : IInitializingObject
|
|
{
|
|
public void AfterPropertiesSet()
|
|
{
|
|
// do some initialization work
|
|
}
|
|
}</programlisting> but does not couple the code to Spring.NET.</para>
|
|
|
|
<note>
|
|
When deploying an object in
|
|
|
|
<literal>prototype</literal>
|
|
|
|
mode, the lifecycle of the object changes slightly. By definition, Spring.NET cannot manage the complete lifecycle of a non-singleton /
|
|
|
|
<literal>prototype</literal>
|
|
|
|
object, since after it is created, it is given to the client and the container no longer keeps a reference to the object. You can think of Spring.NET's role when talking about a non-singleton (
|
|
|
|
<literal>prototype</literal>
|
|
|
|
) object as a replacement for the
|
|
|
|
<literal>new</literal>
|
|
|
|
operator. Any lifecycle aspects past that point have to be handled by the client.
|
|
</note>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-factory-lifecycle-disposableobject">
|
|
<title>IDisposable / <literal>destroy-method</literal></title>
|
|
|
|
<para>The <classname>System.IDisposable</classname> interface provides
|
|
you with the ability to get a callback when an
|
|
<classname>IObjectFactory</classname> is destroyed. The
|
|
<classname>IDisposable</classname> interface specifies exactly one
|
|
method: <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>void Dispose()</literal>: and is called on
|
|
destruction of the container. This allows you to release any
|
|
resources you are keeping in this object (such as database
|
|
connections). You can throw <emphasis>any</emphasis>
|
|
<classname>Exception</classname> here... however, any such
|
|
<classname>Exception</classname> will not stop the destruction
|
|
of the container - it will only get logged.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<note>
|
|
<emphasis>Note: If you choose you can avoid having your class
|
|
implement <classname>IDisposable</classname> since the
|
|
<literal>Spring.Core</literal> library provides support for a
|
|
generic destroy-method, given to the object definition in the object
|
|
configuration store (be it XML, or a database, etc).</emphasis>
|
|
</note>
|
|
|
|
<para><programlisting><object id="exampleInitObject" type="Examples.ExampleObject" destroy-method="cleanup"/>
|
|
[C#]
|
|
public class ExampleObject
|
|
{
|
|
public void cleanup()
|
|
{
|
|
// do some destruction work (such as closing any open connection (s))
|
|
}
|
|
}</programlisting> is exactly the same as: <programlisting><object id="exampleInitObject" type="Examples.AnotherExampleObject"/>
|
|
[C#]
|
|
public class AnotherExampleObject : IDisposable
|
|
{
|
|
public void Dispose()
|
|
{
|
|
// do some destruction work
|
|
}
|
|
}</programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-factory-aware">
|
|
<title>Knowing who you are</title>
|
|
|
|
<sect3 id="objects-factory-aware-objectfactoryaware">
|
|
<title>IObjectFactoryAware</title>
|
|
|
|
<para>A class which implements the
|
|
<classname>Spring.Objects.Factory.IObjectFactoryAware</classname>
|
|
interface is provided with a reference to the
|
|
<classname>IObjectFactory</classname> that created it. The interface
|
|
specifies one (write-only) property: <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>IObjectFactory ObjectFactory</literal>: the
|
|
property that will be set <emphasis>after the initialization
|
|
methods</emphasis> (<literal>AfterPropertiesSet</literal> and
|
|
the init-method).</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>This allows objects to manipulate the
|
|
<classname>IObjectFactory</classname> that created them
|
|
Programatically, through the <classname>IObjectFactory</classname>
|
|
interface, or by casting the reference to a known subclass of this
|
|
which exposes additional functionality. Primarily this would consist
|
|
of programmatic retrieval of other objects. While there are cases when
|
|
this capability is useful, it should generally be avoided, since it
|
|
couples the code to Spring.NET, and does not follow the Inversion of
|
|
Control style, where collaborators are provided to objects as
|
|
properties.</para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-factory-aware-objectnameaware">
|
|
<title>IObjectNameAware</title>
|
|
|
|
<para>The
|
|
<classname>Spring.Objects.Factory.IObjectNameAware</classname>
|
|
interface gives you the ability to let the container set the name of
|
|
the object definition on the object instance itself. In those cases
|
|
where your object needs to know what its name is, implement this
|
|
interface. <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>string ObjectName</literal>: the property that
|
|
will be set to let the object know what its name is.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="objects-childobjects">
|
|
<title>Object definition inheritance</title>
|
|
|
|
<para>An object definition potentially contains a large amount of
|
|
configuration information, including container specific information (i.e.
|
|
initialization method, static factory method name, etc.) and constructor
|
|
arguments and property values. A child object definition is an object
|
|
definition that inherits configuration data from a parent definition. It
|
|
is then able to override some values, or add others, as needed. Using
|
|
parent and child object definitions can potentially save a lot of typing.
|
|
Effectively, this is a form of templating.</para>
|
|
|
|
<para>When working with an <classname>IObjectFactory</classname>
|
|
Programatically, child object definitions are represented by the
|
|
<classname>ChildObjectDefinition</classname> class. Most users will never
|
|
work with them on this level, instead configuring object definitions
|
|
declaratively in something like the
|
|
<classname>XmlObjectFactory</classname>. In an
|
|
<classname>XmlObjectFactory</classname> object definition, a child object
|
|
definition is indicated simply by using the parent attribute, specifying
|
|
the parent object definition as the value of this attribute.</para>
|
|
|
|
<para><programlisting><object id="inheritedTestObject" type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="name" value="parent"/>
|
|
<property name="age" value="1"/>
|
|
</object>
|
|
<object id="inheritsWithDifferentClass" type="Spring.Objects.DerivedTestObject, Spring.Core.Tests"
|
|
parent="inheritedTestObject" init-method="Initialize">
|
|
<property name="name" value="override"/>
|
|
<!-- age will inherit value of 1 from parent -->
|
|
</object></programlisting></para>
|
|
|
|
<para>A child object definition will use the object class from the parent
|
|
definition if none is specified, but can also override it. In the latter
|
|
case, the child object class must be compatible with the parent, i.e. it
|
|
must accept the parent's property values.</para>
|
|
|
|
<para>A child object definition will inherit constructor argument values,
|
|
property values and method overrides from the parent, with the option to
|
|
add new values. If init method, destroy method and/or static factory
|
|
method are specified, they will override the corresponding parent
|
|
settings.</para>
|
|
|
|
<para>The remaining settings will always be taken from the child
|
|
definition: <literal>depends on</literal>, <literal>autowire
|
|
mode</literal>, <literal>dependency check</literal>,
|
|
<literal>singleton</literal>, <literal>lazy init</literal>.</para>
|
|
|
|
<para>In the case where the parent definition does not specify a
|
|
class...</para>
|
|
|
|
<para><programlisting><object id="inheritedTestObjectWithoutClass" abstract="true">
|
|
<property name="name" value="parent"/>
|
|
<property name="age" value="1"/>
|
|
</object>
|
|
<object id="inheritsWithClass" type="Spring.Objects.DerivedTestObject, Spring.Core.Tests"
|
|
parent="inheritedTestObjectWithoutClass" init-method="Initialize">
|
|
<property name="name" value="override"/>
|
|
<!-- age will inherit value of 1 from parent -->
|
|
</object></programlisting></para>
|
|
|
|
<para>... the parent object cannot be instantiated on its own since it
|
|
incomplete, and it is also explicitly marked as abstract. When a
|
|
definition is defined to be abstract like this, it is usable only as a
|
|
pure template object definition that will serve as a parent definition for
|
|
child definitions. Trying to use such an abstract parent object on its own
|
|
(by referring to it as a ref property of another object, or doing an
|
|
explicit <methodname>GetObject()</methodname> with the parent object id),
|
|
will result in an error. The container's internal
|
|
<methodname>PreInstantiateSingletons</methodname> method will completely
|
|
ignore object definitions that are considered abstract.</para>
|
|
|
|
<note>
|
|
Application contexts (but not simple object factories) will by default pre-instantiate all singletons. Therefore it is important (at least for singleton objects) that if you have a (parent) object definition which you intend to use only as a template, and this definition specifies a class, you must make sure to set the
|
|
|
|
<emphasis>abstract</emphasis>
|
|
|
|
attribute to
|
|
|
|
<emphasis>true</emphasis>
|
|
|
|
, otherwise the application context will actually (attempt to) pre-instantiate the abstract object.
|
|
</note>
|
|
</sect1>
|
|
|
|
<sect1 id="objects-factory-extension">
|
|
<title>Interacting with the container</title>
|
|
|
|
<para>The Spring container is essentially nothing more than an advanced
|
|
factory capable of maintaining a registry of different objects and their
|
|
dependencies. The <classname>IObjectFactory</classname> enables you to
|
|
read object definitions and access them using the object factory. When
|
|
using just the <classname>IObjectFactory</classname> you would create an
|
|
instance of one and then read in some object definitions in the XML format
|
|
as follows: <programlisting>[C#]
|
|
IResource input = new FileSystemResource ("objects.xml");
|
|
XmlObjectFactory factory = new XmlObjectFactory(input);</programlisting></para>
|
|
|
|
<para>That is pretty much it. Using <literal>GetObject(string)</literal>
|
|
(or the more concise indexer method <literal>factory ["string"]</literal>)
|
|
you can retrieve instances of your objects... <programlisting>[C#]
|
|
object foo = factory.GetObject ("foo"); // gets the object defined as 'foo'
|
|
object bar = factory ["bar"]; // same thing, just using the indexer
|
|
</programlisting></para>
|
|
|
|
<para>You'll get a reference to the same object if you defined it as a
|
|
singleton (the default) or you'll get a new instance each time if you set
|
|
the <literal>singleton</literal> property of your object definition to
|
|
<emphasis>false</emphasis>. <programlisting><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/>
|
|
<object id="anotherObject" type="Examples.ExampleObject, ExamplesLibrary" singleton="false"/></programlisting>
|
|
<programlisting>[C#]
|
|
object one = factory ["exampleObject"]; // gets the object defined as 'exampleObject'
|
|
object two = factory ["exampleObject"];
|
|
Console.WriteLine (one == two) // prints 'true'
|
|
object three = factory ["anotherObject"]; // gets the object defined as 'anotherObject'
|
|
object four = factory ["anotherObject"];
|
|
Console.WriteLine (three == four); // prints 'false'
|
|
</programlisting></para>
|
|
|
|
<para>The client-side view of the <classname>IObjectFactory</classname> is
|
|
surprisingly simple. The <classname>IObjectFactory</classname> interface
|
|
has only seven methods (and the aforementioned indexer) for clients to
|
|
call: <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>bool ContainsObject(string)</literal>: returns true
|
|
if the <classname>IObjectFactory</classname> contains an object
|
|
definition that matches the given name.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>object GetObject(string)</literal>: returns an
|
|
instance of the object registered under the given name. Depending on
|
|
how the object was configured by the
|
|
<classname>IObjectFactory</classname> configuration, either a
|
|
singleton (and thus shared) instance or a newly created object will
|
|
be returned. An <literal>ObjectsException</literal> will be thrown
|
|
when either the object could not be found (in which case it'll be a
|
|
<literal>NoSuchObjectDefinitionException</literal>), or an exception
|
|
occurred while instantiated and preparing the object.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Object this [string]</literal>: this is the indexer
|
|
for the <classname>IObjectFactory</classname> interface. It
|
|
functions in all other respects in exactly the same way as the
|
|
<literal>GetObject(string)</literal> method. The rest of this
|
|
documentation will always refer to the
|
|
<literal>GetObject(string)</literal> method, but be aware that you
|
|
can use the indexer anywhere that you can use the
|
|
<literal>GetObject(string)</literal> method.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Object GetObject(string, Type)</literal>: returns an
|
|
object, registered under the given name. The object returned will be
|
|
cast to the given <classname>Type</classname>. If the object could
|
|
not be cast, corresponding exceptions will be thrown
|
|
(<literal>ObjectNotOfRequiredTypeException</literal>). Furthermore,
|
|
all rules of the <literal>GetObject(string)</literal> method apply
|
|
(see above).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>bool IsSingleton(string)</literal>: determines
|
|
whether or not the object definition registered under the given name
|
|
is a singleton or a prototype. If the object definition
|
|
corresponding to the given name could not be found, an exception
|
|
will be thrown
|
|
(<literal>NoSuchObjectDefinitionException</literal>)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string[] GetAliases(string)</literal>: returns the
|
|
aliases for the given object name, if any were defined in the
|
|
<classname>IObjectDefinition</classname>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void ConfigureObject(object target):</literal>
|
|
Injects dependencies into the supplied target instance. The name of
|
|
the abstract object definition is the
|
|
<literal>System.Type.FullName</literal> of the target instance. This
|
|
method is typically used when objects are instantiated outside the
|
|
control of a developer, for example when ASP.NET instantiates web
|
|
controls and when a WinForms application creates
|
|
UserControls.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void ConfigureObject(object target, string
|
|
name):</literal> Offers the same functionality as the previously
|
|
listed Configure method but uses a named object definition instead
|
|
of using the type's full name.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>A sub-interface of <classname>IObjectFactory</classname>,
|
|
<classname>IConfigurableObjectFactory</classname> adds some convenient
|
|
methods such as</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>void RegisterSingleton(string name, object
|
|
objectInstance)</literal> : Register the given existing object as
|
|
singleton in the object factory under the given object name.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void RegisterAlias(string name, string
|
|
theAlias)</literal>; Given an object name, create an alias.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Check the SDK docs for additional details on
|
|
IConfigurableObjectFactory methods and properties and the full
|
|
<classname>IObjectFactory</classname> class hierarchy.</para>
|
|
|
|
<sect2>
|
|
<title>Obtaining an <classname>IFactoryObject</classname>, not its
|
|
product</title>
|
|
|
|
<para>Sometimes there is a need to ask an
|
|
<classname>IObjectFactory</classname> for an actual
|
|
<classname>IFactoryObject</classname> instance itself, not the object it
|
|
produces. This may be done by prepending the object id with
|
|
<literal>&</literal> when calling the
|
|
<methodname>GetObject</methodname> method of the
|
|
<classname>IObjectFactory</classname> and
|
|
<classname>IApplicationContext</classname> interfaces. So for a given
|
|
<classname>IFactoryObject</classname> with an id
|
|
<literal>myObject</literal>, invoking
|
|
<literal>GetObject("myObject")</literal> on the
|
|
<classname>IObjectFactory</classname> will return the product of the
|
|
<classname>IFactoryObject</classname>, but invoking
|
|
<literal>GetObject("&myObject")</literal> will return the
|
|
<classname>IFactoryObject</classname> instance itself.</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Container extension points</title>
|
|
|
|
<para>The IoC component of the Spring Framework has been designed for
|
|
extension. There is typically no need for an application developer to
|
|
subclass any of the various <classname>IObjectFactory</classname> or
|
|
<classname>IApplicationContext</classname> implementation classes. The
|
|
Spring IoC container can be infinitely extended by plugging in
|
|
implementations of special integration interfaces. The next few sections
|
|
are devoted to detailing all of these various integration
|
|
interfaces.</para>
|
|
|
|
<sect2 id="objects-factory-customizing">
|
|
<title>Customizing objects with
|
|
<literal>IObjectPostProcessors</literal></title>
|
|
|
|
<para>The first extension point that we will look at is the
|
|
<classname>Spring.Objects.Factory.Config.IObjectPostProcessor</classname>
|
|
interface. This interface defines a number of callback methods that you
|
|
as an application developer can implement in order to provide your own
|
|
(or override the containers default) instantiation logic,
|
|
dependency-resolution logic, and so forth. If you want to do some custom
|
|
logic after the Spring container has finished instantiating, configuring
|
|
and otherwise initializing an object, you can plug in one or more
|
|
<classname>IObjectPostProcessor</classname> implementations.</para>
|
|
|
|
<para>You can configure multiple
|
|
<classname>IObjectPostProcessors</classname> if you wish. You can
|
|
control the order in which these
|
|
<classname>IObjectPostProcessor</classname> execute by setting the
|
|
'Order' property (you can only set this property if the
|
|
<classname>IObjectPostProcessor</classname> implements the
|
|
<classname>IOrdered</classname> interface; if you write your own
|
|
<classname>IObjectPostProcessor</classname> you should consider
|
|
implementing the <classname>IOrdered</classname> interface too); consult
|
|
the SDK docs for the <classname>IObjectPostProcessor</classname> and
|
|
<classname>IOrdered</classname> interfaces for more details.</para>
|
|
|
|
<note>
|
|
<para><classname>IObjectPostProcessor</classname> operate on object
|
|
instances; that is to say, the Spring IoC container will have
|
|
instantiated a object instance for you, and then
|
|
<classname>IObjectPostProcessors</classname> get a chance to do their
|
|
stuff. If you want to change the actual object definition (that is the
|
|
recipe that defines the object), then you rather need to use a
|
|
<classname>IObjectFactoryPostProcessor</classname> (described below in
|
|
the section entitled <link
|
|
linkend="objects-factory-customizing-factory-postprocessors">Customizing
|
|
configuration metadata with
|
|
IObjectFactoryPostProcessors.</link></para>
|
|
|
|
<para>Also, <classname>IObjectPostProcessors</classname> are scoped
|
|
per-container. This is only relevant if you are using container
|
|
hierarchies. If you define a
|
|
<classname>IObjectPostProcessor</classname> in one container, it will
|
|
only do its stuff on the objects in that container. Objects that are
|
|
defined in another container will not be post-processed by
|
|
<classname>IObjectPostProcessors</classname> in another container,
|
|
even if both containers are part of the same hierarchy.</para>
|
|
</note>
|
|
|
|
<para>The
|
|
<classname>Spring.Objects.Factory.Config.IObjectPostProcessor</classname>
|
|
interface, which consists of two callback methods shown below.
|
|
<programlisting>object PostProcessBeforeInitialization(object instance, string name);
|
|
|
|
object PostProcessAfterInitialization(object instance, string name);</programlisting>When
|
|
such a class is registered as a post-processor with the container, for
|
|
each object instance that is created by the container,(see below for how
|
|
this registration is effected), for each object instance that is created
|
|
by the container, the post-processor will get a callback from the
|
|
container both <emphasis>before</emphasis> any initialization methods
|
|
(such as the <methodname>AfterPropertiesSet</methodname> method of the
|
|
<classname>IInitializingObject</classname> interface and any declared
|
|
init method) are called, and also afterwards. The post-processor is free
|
|
to do what it wishes with the object, including ignoring the callback
|
|
completely. An object post-processor will typically check for marker
|
|
interfaces, or do something such as wrap an object with a proxy. Some
|
|
Spring.NET AOP infrastructure classes are implemented as object
|
|
post-processors as they do this proxy-wrapping logic.</para>
|
|
|
|
<para>Other extensions to the <literal>IObjectPostProcessors</literal>
|
|
interface are
|
|
<classname>IInstantiationAwareObjectPostProcessor</classname> and
|
|
<classname>IDestructionAwareObjectPostProcessor</classname> defined
|
|
below <programlisting>public interface IInstantiationAwareObjectPostProcessor : IObjectPostProcessor
|
|
{
|
|
object PostProcessBeforeInstantiation(Type objectType, string objectName);
|
|
|
|
bool PostProcessAfterInstantiation(object objectInstance, string objectName);
|
|
|
|
IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, PropertyInfo[] pis, object objectInstance, string objectName);
|
|
}
|
|
|
|
public interface IDestructionAwareObjectPostProcessor : IObjectPostProcessor
|
|
{
|
|
void PostProcessBeforeDestruction (object instance, string name);
|
|
}</programlisting> The <classname>PostProcessBeforeInstantiation</classname>
|
|
callback method is called right before the container creates the object.
|
|
If the object returned by this method is not null then the default
|
|
instantiation behavior of the container is short circuited. The returned
|
|
object is the one registered with the container and no other
|
|
<literal>IObjectPostProcessor</literal> callbacks will be invoked on it.
|
|
This mechanism is useful if you would like to expose a proxy to the
|
|
object instead of the actual target object. The
|
|
<classname>PostProcessAfterInstantiation</classname> callback method is
|
|
called after the object has been instantiated but before Spring performs
|
|
property population based on explicit properties or autowiring. A return
|
|
value of false would short circuit the standard Spring based property
|
|
population. The callback method
|
|
<classname>PostProcessPropertyValues</classname> is called after Spring
|
|
collects all the property values to apply to the object, but before they
|
|
are applied. This gives you the opportunity to perform additional
|
|
processing such as making sure that a property is set to a value if it
|
|
contains a <classname>[Required]</classname> attribute or to perform
|
|
attribute based wiring, i.e. adding the attribute
|
|
<classname>[Inject("objectName")]</classname> on a property. Both of
|
|
these features are scheduled to be included in Spring .12.</para>
|
|
|
|
<para>The <classname>IDestructionAwareObjectPostProcessor</classname>
|
|
callback contains a single method,
|
|
<classname>PostProcessBeforeDestruction</classname>, which is called
|
|
before a singleton's destroy method is invoked.</para>
|
|
|
|
<para>It is important to know that the
|
|
<classname>IObjectFactory</classname> treats object post-processors
|
|
slightly differently than the
|
|
<classname>IApplicationContext</classname>. An
|
|
<classname>IApplicationContext</classname> will automatically detect any
|
|
objects which are deployed into it that implement the
|
|
<classname>IObjectPostProcessor</classname> interface, and register them
|
|
as post-processors, to be then called appropriately by the factory on
|
|
object creation. Nothing else needs to be done other than deploying the
|
|
post-processor in a similar fashion to any other object. On the other
|
|
hand, when using plain <literal>IObjectFactories</literal>, object
|
|
post-processors have to manually be explicitly registered, with a code
|
|
sequence such as... <programlisting>ConfigurableObjectFactory factory = new .....; // create an IObjectFactory
|
|
... // now register some objects
|
|
// now register any needed IObjectPostProcessors
|
|
MyObjectPostProcessor pp = new MyObjectPostProcessor();
|
|
factory.AddObjectPostProcessor(pp);
|
|
// now start using the factory
|
|
...</programlisting></para>
|
|
|
|
<para>This explicit registration step is not convenient, and this is one
|
|
of the reasons why the various
|
|
<classname>IApplicationContext</classname> implementations are preferred
|
|
above plain <classname>IObjectFactory</classname> implementations in the
|
|
vast majority of Spring-backed applications, especially when using
|
|
IObjectPostProcessors.</para>
|
|
|
|
<note>
|
|
<para>IObjectPostProcessors and AOP auto-proxying</para>
|
|
|
|
<para>Classes that implement the
|
|
<classname>IObjectPostProcessor</classname> interface are special, and
|
|
so they are treated differently by the container. All
|
|
<classname>IObjectPostProcessors</classname> and their directly
|
|
referenced object will be instantiated on startup, as part of the
|
|
special startup phase of the IApplicationContext, then all those
|
|
<classname>IObjectPostProcessors</classname> will be registered in a
|
|
sorted fashion - and applied to all further objects. Since AOP
|
|
auto-proxying is implemented as a
|
|
<classname>IObjectPostProcessor</classname> itself, no
|
|
<classname>IObjectPostProcessors</classname> or directly referenced
|
|
objects are eligible for auto-proxying (and thus will not have aspects
|
|
'woven' into them). For any such object, you should see an info log
|
|
message: “Object 'foo' is not eligible for getting processed by all
|
|
<classname>IObjectPostProcessors</classname> (for example: not
|
|
eligible for auto-proxying)”.</para>
|
|
</note>
|
|
|
|
<para></para>
|
|
|
|
<sect3 id="object-factory-extension-opp-examples-hw">
|
|
<title>Example: Hello World, IObjectPostProcessor-style</title>
|
|
|
|
<para>This first example is hardly compelling, but serves to
|
|
illustrate basic usage. All we are going to do is code a custom
|
|
IObjectPostProcessor implementation that simply invokes the ToString()
|
|
method of each object as it is created by the container and prints the
|
|
resulting string to the system console. Yes, it is not hugely useful,
|
|
but serves to get the basic concepts across before we move into the
|
|
second example which is actually useful. The basis of the example is
|
|
the MovieFinder quickstart that is included with the Spring.NET
|
|
distribution.</para>
|
|
|
|
<para>Find below the custom IObjectPostProcessor implementation class
|
|
definition</para>
|
|
|
|
<para><programlisting>using System;
|
|
using Spring.Objects.Factory.Config;
|
|
|
|
namespace Spring.IocQuickStart.MovieFinder
|
|
{
|
|
public class TracingObjectPostProcessor : IObjectPostProcessor
|
|
{
|
|
public object PostProcessBeforeInitialization(object instance, string name)
|
|
{
|
|
return instance;
|
|
}
|
|
|
|
public object PostProcessAfterInitialization(object instance, string name)
|
|
{
|
|
Console.WriteLine("Object '" + name + "' created : " + instance.ToString());
|
|
return instance;
|
|
}
|
|
}
|
|
}</programlisting>And the following configuration</para>
|
|
|
|
<programlisting><?xml version="1.0" encoding="utf-8" ?>
|
|
<objects xmlns="http://www.springframework.net" >
|
|
<description>An example that demonstrates simple IoC features.</description>
|
|
|
|
<object id="MyMovieLister"
|
|
type="Spring.IocQuickStart.MovieFinder.MovieLister, Spring.IocQuickStart.MovieFinder">
|
|
<property name="movieFinder" ref="MyMovieFinder"/>
|
|
</object>
|
|
|
|
<object id="MyMovieFinder"
|
|
type="Spring.IocQuickStart.MovieFinder.SimpleMovieFinder, Spring.IocQuickStart.MovieFinder"/>
|
|
|
|
<!-- when the above objects are instantiated, this custom IObjectPostProcessor implementation
|
|
will output the fact to the system console -->
|
|
<emphasis role="bold"><object type="Spring.IocQuickStart.MovieFinder.TracingObjectPostProcessor, Spring.IocQuickStart.MovieFinder"/></emphasis>
|
|
</objects></programlisting>
|
|
|
|
<para>Notice how the TracingObjectPostProcessor is simply defined; it
|
|
doesn't even have a name, and because it is a object it can be
|
|
dependency injected just like any other object.</para>
|
|
|
|
<para>Find below a small driver script to exercise the above code and
|
|
configuration;</para>
|
|
|
|
<para><programlisting>IApplicationContext ctx =
|
|
new XmlApplicationContext(
|
|
"assembly://Spring.IocQuickStart.MovieFinder/Spring.IocQuickStart.MovieFinder/AppContext.xml");
|
|
|
|
MovieLister lister = (MovieLister) ctx.GetObject("MyMovieLister");
|
|
Movie[] movies = lister.MoviesDirectedBy("Roberto Benigni");
|
|
LOG.Debug("Searching for movie...");
|
|
foreach (Movie movie in movies)
|
|
{
|
|
LOG.Debug(string.Format("Movie Title = '{0}', Director = '{1}'.", movie.Title, movie.Director));
|
|
}
|
|
LOG.Debug("MovieApp Done.");</programlisting>The output of executing the above
|
|
program will be:</para>
|
|
|
|
<programlisting>INFO - Object 'Spring.IocQuickStart.MovieFinder.TracingObjectPostProcessor' is not eligible for being processed by all IObjectPostProcessors
|
|
(for example: not eligible for auto-proxying).
|
|
Object 'MyMovieFinder' created : Spring.IocQuickStart.MovieFinder.SimpleMovieFinder
|
|
Object 'MyMovieLister' created : Spring.IocQuickStart.MovieFinder.MovieLister
|
|
DEBUG - Searching for movie...
|
|
DEBUG - Movie Title = 'La vita e bella', Director = 'Roberto Benigni'.
|
|
DEBUG - MovieApp Done.</programlisting>
|
|
</sect3>
|
|
|
|
<sect3 id="object-factory-extension-opp-examplesrapp">
|
|
<title>Example: the RequiredAttributeObjectPostProcessor</title>
|
|
|
|
<para>Using callback interfaces or annotations in conjunction with a
|
|
custom IObjectPostProcessor implementation is a common means of
|
|
extending the Spring IoC container. The <literal>[Required]</literal>
|
|
attribute in the <literal>Spring.Objects.Factory.Attributes</literal>
|
|
namespace can be used to <emphasis>mark</emphasis> a property as
|
|
being<emphasis> 'required-to-be-set' </emphasis>(i.e. an setter
|
|
property with this attribute applied must be configured to be
|
|
dependency injected with a value), else an
|
|
<classname>ObjectInitializationException</classname> will be thrown by
|
|
the container at runtime.</para>
|
|
|
|
<para>The best way to illustrate the usage of this attribute is with
|
|
an example.</para>
|
|
|
|
<programlisting>public class MovieLister
|
|
{
|
|
// the MovieLister has a dependency on the MovieFinder
|
|
private IMovieFinder _movieFinder;
|
|
|
|
// a setter property so that the Spring container can 'inject' a MovieFinder
|
|
[Required]
|
|
public IMovieFinder MovieFinder
|
|
{
|
|
set { _movieFinder = value; }
|
|
}
|
|
|
|
// business logic that actually 'uses' the injected MovieFinder is omitted...
|
|
|
|
}</programlisting>
|
|
|
|
<para>Hopefully the above class definition reads easy on the eye. Any
|
|
and all <literal>IObjectDefinitions</literal> for the
|
|
<classname>MovieLister</classname> class must be provided with a
|
|
value.</para>
|
|
|
|
<para>Let's look at an example of some XML configuraiton that will not
|
|
pass validation.</para>
|
|
|
|
<programlisting> <object id="MyMovieLister"
|
|
type="Spring.IocQuickStart.MovieFinder.MovieLister, Spring.IocQuickStart.MovieFinder">
|
|
<!-- whoops, no MovieFinder is set (and this property is [Required]) -->
|
|
</object></programlisting>
|
|
|
|
<para>At runtime the following message will be generated by the Spring
|
|
container</para>
|
|
|
|
<programlisting>Error creating context 'spring.root': Property 'MovieFinder' required for object 'MyMovieLister'</programlisting>
|
|
|
|
<para>There is one last little piece of Spring configuration that is
|
|
required to actually 'switch on' this behavior. Simply annotating the
|
|
'setter' properties of your classes is not enough to get this
|
|
behavior. You need to enable a component that is aware of the
|
|
<literal>[Required]</literal> attribute and that can process it
|
|
appropriately.</para>
|
|
|
|
<para>This component is the
|
|
<classname>RequiredAttributeObjectPostProcessor</classname> class.
|
|
This is a special <literal>IObjectPostProcessor</literal>
|
|
implementation that is <literal>[Required]</literal>-aware and
|
|
actually provides the 'blow up if this required property has not been
|
|
set' logic. It is very easy to configure; simply drop the following
|
|
object definition into your Spring XML configuration.</para>
|
|
|
|
<programlisting><object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"/></programlisting>
|
|
|
|
<para>Finally, one can configure an instance of the
|
|
<classname>RequiredAttributeObjectPostProcessor</classname> class to
|
|
look for another <literal>Attribute</literal> type. This is great if
|
|
you already have your own <literal>[Required]</literal>-style
|
|
attribute. Simply plug it into the definition of a
|
|
<classname>RequiredAttributeObjectPostProcessor</classname> and you
|
|
are good to go. By way of an example, let's suppose you (or your
|
|
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">
|
|
<property name="RequiredAttributeType" value="MyApp.Attributes.MandatoryAttribute, MyApp"/>
|
|
</object></programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-factory-customizing-factory-postprocessors">
|
|
<title>Customizing configuration metadata with
|
|
ObjectFactoryPostProcessors</title>
|
|
|
|
<para>The next extension point that we will look at is the
|
|
<classname>Spring.Objects.Factory.Config.IObjectFactoryPostProcessor</classname>.
|
|
The semantics of this interface are similar to the
|
|
<classname>IObjectPostProcessor</classname>, with one major difference.
|
|
<classname>IObjectFactoryPostProcessors</classname> operate on; that is
|
|
to say, the Spring IoC container will allow
|
|
<classname>IObjectFactoryPostProcessors</classname> to read the
|
|
configuration metadata and potentially change it before the container
|
|
has actually instantiated any other objects. By implementing this
|
|
interface, you will receive a callback after the all the object
|
|
definitions have been loaded into the IoC container but before they have
|
|
been instantiated. The signature of the interface is shown below
|
|
<programlisting>public interface IObjectFactoryPostProcessor
|
|
{
|
|
void PostProcessObjectFactory (IConfigurableListableObjectFactory factory);
|
|
}
|
|
</programlisting></para>
|
|
|
|
<para>You can configure multiple
|
|
<classname>IObjectFactoryPostProcessors</classname> if you wish. You can
|
|
control the order in which these
|
|
<classname>IObjectFactoryPostProcessors</classname> execute by setting
|
|
the 'Order' property (you can only set this property if the
|
|
<classname>IObjectFactoryPostProcessors</classname> implements the
|
|
<classname>IOrdered</classname> interface; if you write your own
|
|
<classname>IObjectFactoryPostProcessors</classname> you should consider
|
|
implementing the <classname>IOrdered</classname> interface too); consult
|
|
the SDK docs for the <classname>IObjectFactoryPostProcessors</classname>
|
|
and <classname>IOrdered</classname> interfaces for more details.</para>
|
|
|
|
<note>
|
|
<para>If you want to change the actual object instances (the objects
|
|
that are created from the configuration metadata), then you rather
|
|
need to use a <classname>IObjectObjectPostProcessor</classname>
|
|
(described above in the section entitled <link
|
|
linkend="objects-factory-customizing">Customizing objects with
|
|
<literal>IObjectPostProcessors</literal></link>.</para>
|
|
|
|
<para>Also, <classname>IObjectFactoryPostProcessors</classname> are
|
|
scoped per-container. This is only relevant if you are using container
|
|
hierarchies. If you define a
|
|
<classname>IObjectFactoryPostProcessors</classname> in one container,
|
|
it will only do its stuff on the object definitions in that container.
|
|
Object definitions in another container will not be post-processed by
|
|
<classname>IObjectFactoryPostProcessors</classname> in another
|
|
container, even if both containers are part of the same
|
|
hierarchy.</para>
|
|
</note>
|
|
|
|
<para>An object factory post-processor is executed manually (in the case
|
|
of a IObjectFactory) or automatically (in the case of an
|
|
IApplicationContext) to apply changes of some sort to the configuration
|
|
metadata that defines a container. Spring.NET includes a number of
|
|
pre-existing object factory post-processors, such as
|
|
<literal>PropertyResourceConfigurer</literal> and
|
|
<literal>PropertyPlaceHolderConfigurer</literal>, both described below
|
|
and ObjectNameAutoProxyCreator, which is very useful for wrapping other
|
|
objects transactionally or with any other kind of proxy, as described
|
|
later in this manual.</para>
|
|
|
|
<para>In an <classname>IObjectFactory</classname>, the process of
|
|
applying an <classname>IObjectFactoryPostProcessor</classname> is
|
|
manual, and will be similar to this:</para>
|
|
|
|
<para><programlisting>XmlObjectFactory factory = new XmlObjectFactory(new FileSystemResource("objects.xml"));
|
|
<lineannotation>// create placeholderconfigurer to bring in some property
|
|
// values from a Properties file</lineannotation>
|
|
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
|
|
cfg.setLocation(new FileSystemResource("ado.properties"));
|
|
<lineannotation>// now actually do the replacement</lineannotation>
|
|
cfg.PostProcessObjectFactory(factory);</programlisting></para>
|
|
|
|
<para><anchor
|
|
id="objects-factory-autodetect-objectfactorypostprocessors" />This
|
|
explicit registration step is not convenient, and this is one of the
|
|
reasons why the various <classname>IApplicationContext</classname>
|
|
implementations are preferred above plain
|
|
<classname>IObjectFactory</classname> implementations in the vast
|
|
majority of Spring-backed applications, especially when using
|
|
<classname>IObjectFactoryPostProcessors</classname>.</para>
|
|
|
|
<para>An <classname>IApplicationContext</classname> will detect any
|
|
objects which are deployed into it that implement the
|
|
<literal>ObjectFactoryPostProcessor</literal> interface, and
|
|
automatically use them as object factory post-processors, at the
|
|
appropriate time. Nothing else needs to be done other than deploying
|
|
these post-processor in a similar fashion to any other object.</para>
|
|
|
|
<note>
|
|
<para>Just as in the case of
|
|
<classname>IObjectPostProcessors</classname>, you typically don't want
|
|
to have <classname>IObjectFactoryPostProcessors</classname> marked as
|
|
being lazily-initialized. If they are marked as such, then the Spring
|
|
container will never instantiate them, and thus they won't get a
|
|
chance to apply their custom logic. If you are using the
|
|
'default-lazy-init' attribute on the declaration of your
|
|
<objects/> element, be sure to mark your various
|
|
<classname>IObjectFactoryPostProcessor</classname> object definitions
|
|
with 'lazy-init="false"'.</para>
|
|
</note>
|
|
|
|
<sect3 id="objects-factory-placeholderconfigurer">
|
|
<title>Example: The
|
|
<classname>PropertyPlaceholderConfigurer</classname></title>
|
|
|
|
<para>The <classname>PropertyPlaceholderConfigurer</classname> is an
|
|
excellent solution when you want to externalize a few properties from
|
|
a file containing object definitions. This is useful to allow the
|
|
person deploying an application to customize environment specific
|
|
properties (for example database configuration strings, usernames, and
|
|
passwords), without the complexity or risk of modifying the main XML
|
|
definition file or files for the container.</para>
|
|
|
|
<para>Variable substitution is performed on simple property values,
|
|
lists, dictionaries, sets, constructor values, object type name, and
|
|
object names in runtime object references. Furthermore, placeholder
|
|
values can also cross-reference other placeholders.</para>
|
|
|
|
<para>Note that <literal>IApplicationContext</literal>s are able to
|
|
automatically recognize and apply objects deployed in them that
|
|
implement the <classname>IObjectFactoryPostProcessor</classname>
|
|
interface. This means that as described here, applying a
|
|
<classname>PropertyPlaceholderConfigurer</classname> is much more
|
|
convenient when using an <classname>IApplicationContext</classname>.
|
|
For this reason, it is recommended that users wishing to use this or
|
|
other object factory postprocessors use an
|
|
<classname>IApplicationContext</classname> instead of an
|
|
<classname>IObjectFactory</classname>.</para>
|
|
|
|
<para>In the example below a data access object needs to be configured
|
|
with a database connection and also a value for the maximum number of
|
|
results to return in a query. Instead of hard coding the values into
|
|
the main Spring.NET configuration file we use place holders, in the
|
|
NAnt style of ${variableName}, and obtain their values from
|
|
NameValueSections in the standard .NET application configuration file.
|
|
The Spring.NET configuration file looks like: <programlisting><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
<section name="DaoConfiguration" type="System.Configuration.NameValueSectionHandler"/>
|
|
<section name="DatabaseConfiguration" type="System.Configuration.NameValueSectionHandler"/>
|
|
</configSections>
|
|
|
|
<DaoConfiguration>
|
|
<add key="maxResults" value="1000"/>
|
|
</DaoConfiguration>
|
|
|
|
<DatabaseConfiguration>
|
|
<add key="connection.string" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/>
|
|
</DatabaseConfiguration>
|
|
|
|
<spring>
|
|
<context>
|
|
<resource uri="assembly://DaoApp/DaoApp/objects.xml"/>
|
|
</context>
|
|
</spring>
|
|
|
|
</configuration></programlisting></para>
|
|
|
|
<para>Notice the presence of two NameValueSections in the
|
|
configuration file. These name value pairs will be referred to in the
|
|
Spring.NET configuration file. In this example we are using an
|
|
embedded assembly resource for the location of the Spring.NET
|
|
configuration file so as to reduce the chance of accidental tampering
|
|
in deployment. This Spring.NET configuration file is shown
|
|
below.</para>
|
|
|
|
<programlisting><objects xmlns="http://www.springframework.net"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.springframework.net
|
|
http://www.springframework.net/xsd/spring-objects.xsd" >
|
|
|
|
<object name="productDao" type="DaoApp.SimpleProductDao, DaoApp ">
|
|
<property name="maxResults" value="<emphasis role="bold">${maxResults}</emphasis>"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
</object>
|
|
|
|
<object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data">
|
|
<property name="connectionstring" value="<emphasis role="bold">${connection.string}</emphasis>"/>
|
|
</object>
|
|
|
|
<object name="appConfigPropertyHolder"
|
|
type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
|
|
|
|
<property name="configSections">
|
|
<value>DaoConfiguration,DatabaseConfiguration</value>
|
|
</property>
|
|
|
|
</object>
|
|
</objects></programlisting>
|
|
|
|
<para>The values of <literal>${maxResults}</literal> and
|
|
<literal>${connection.string}</literal> match the key names used in
|
|
the two NameValueSectionHandlers <literal>DaoConfiguration</literal>
|
|
and <literal>DatabaseConfiguration</literal>. The
|
|
<classname>PropertyPlaceholderConfigurer</classname> refers to these
|
|
two sections via a comma delimited list of section names in the
|
|
<literal>configSections</literal> property. If you are using section
|
|
groups, prefix the section group name, for example
|
|
myConfigSection/DaoConfiguraiton.</para>
|
|
|
|
<para>The <classname>PropertyPlaceholderConfigurer</classname> class
|
|
also supports retrieving name value pairs from other
|
|
<classname>IResource</classname> locations. These can be specified
|
|
using the <literal>Location</literal> and <literal>Locations</literal>
|
|
properties of the <classname>PropertyPlaceHolderConfigurer</classname>
|
|
class.</para>
|
|
|
|
<para>If there are properties with the same name in different resource
|
|
locations the default behavior is that the last property processed
|
|
overrides the previous values. This is behavior is controlled by the
|
|
<literal>LastLocationOverrides</literal> property. True enables
|
|
overriding while false will append the values as one would normally
|
|
expect using <literal>NameValueCollection.Add</literal>.</para>
|
|
|
|
<note>
|
|
In an ASP.NET environment you must specify the full, four-part name of the assembly when using a
|
|
|
|
<classname>NameValueFileSectionHandler</classname>
|
|
|
|
|
|
|
|
<programlisting>
|
|
<section name="hibernateConfiguration"
|
|
type="System.Configuration.NameValueFileSectionHandler, System,
|
|
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
|
</programlisting>
|
|
|
|
|
|
</note>
|
|
|
|
<sect4>
|
|
<title>Type, Ref, and Expression substitution</title>
|
|
|
|
<para>The PropertyPlaceholderConfigurer can be used to substitute
|
|
type names, which is sometimes useful when you have to pick a
|
|
particular implementation class at runtime. For example:</para>
|
|
|
|
<programlisting> <object id="MyMovieFinder" type="${custom.moviefinder.type}"/></programlisting>
|
|
|
|
<para>If the class is unable to be resolved at runtime to a valid
|
|
type, resolution of the object will fail once it is about to be
|
|
created (which is during the PreInstantiateSingletons() phase of an
|
|
ApplicationContext for a non-lazy-init object.)</para>
|
|
|
|
<para>Similarly you can replace 'ref' and 'expression' metadata, as
|
|
shown below</para>
|
|
|
|
<programlisting><object id="TestObject" type="Simple.TestObject, MyAssembly">
|
|
<property name="age" expression="${ageExpression}"/>
|
|
<property name="spouse" ref="${spouse-ref}"/>
|
|
</object></programlisting>
|
|
</sect4>
|
|
|
|
<sect4 id="objects-factory-placeholderconfigurer-envvars">
|
|
<title>Replacement with Environment Variables</title>
|
|
|
|
<para>You may also use the value environment variables to replace
|
|
property placeholders. The use of environment variables is
|
|
controlled via the property
|
|
<literal>EnvironmentVariableMode</literal>. This property is an
|
|
enumeration of the type
|
|
<classname>EnvironmentVariablesMode</classname> and has three
|
|
values, Never, Fallback, and Override. <literal>Fallback</literal>
|
|
is the default value and will resolve a property placeholder if it
|
|
was not already done so via a value from a resource location.
|
|
<literal>Override</literal> will apply environment variables before
|
|
applying values defined from a resource location.
|
|
<literal>Never</literal> will, quite appropriately, disable
|
|
environment variable substitution. An example of how the
|
|
<classname>PropertyPlaceholderConfigurer</classname> XML is modified
|
|
to enable override usage is shown below <programlisting><object name="appConfigPropertyHolder"
|
|
type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
|
|
<property name="configSections" value="DaoConfiguration,DatabaseConfiguration"/>
|
|
<property name="EnvironmentVariableMode" value="Override"/>
|
|
</object>
|
|
</objects></programlisting></para>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-factory-overrideconfigurer">
|
|
<title>Example: The
|
|
<classname>PropertyOverrideConfigurer</classname></title>
|
|
|
|
<para>The <classname>PropertyOverrideConfigurer</classname>, another
|
|
object factory post-processor, is similar to the
|
|
<classname>PropertyPlaceholderConfigurer</classname>, but in contrast
|
|
to the latter, the original definitions can have default values or no
|
|
values at all for object properties. If an overriding configuration
|
|
file does not have an entry for a certain object property, the default
|
|
context definition is used.</para>
|
|
|
|
<para>Note that the object factory definition is
|
|
<emphasis>not</emphasis> aware of being overridden, so it is not
|
|
immediately obvious when looking at the XML definition file that the
|
|
override configurer is being used. In case that there are multiple
|
|
<classname>PropertyOverrideConfigurer</classname> instances that
|
|
define different values for the same object property, the last one
|
|
will win (due to the overriding mechanism).</para>
|
|
|
|
<para>The example usage is similar to when using
|
|
<classname>PropertyPlaceHolderConfigurer</classname> except that the
|
|
key name refers to the name given to the object in the Spring.NET
|
|
configuration file and is suffixed via 'dot' notation with the name of
|
|
the property For example, if the application configuration file is
|
|
<programlisting><configuration>
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
<section name="DaoConfigurationOverride" type="System.Configuration.NameValueSectionHandler"/>
|
|
</configSections>
|
|
|
|
<DaoConfigurationOverride>
|
|
<add key="productDao.maxResults" value="1000"/>
|
|
</DaoConfigurationOverride>
|
|
|
|
<spring>
|
|
<context>
|
|
<resource uri="assembly://DaoApp/DaoApp/objects.xml"/>
|
|
</context>
|
|
</spring>
|
|
|
|
</configuration></programlisting> Then the value of 1000 will be used to
|
|
overlay the value of 2000 set in the Spring.NET configuration file
|
|
shown below <programlisting><objects xmlns="http://www.springframework.net"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd" >
|
|
|
|
<object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp " >
|
|
<property name="maxResults" value="2000"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
<property name="log" ref="daoLog"/>
|
|
</object>
|
|
|
|
<object name="daoLog" type="Spring.Objects.Factory.Config.LogFactoryObject, Spring.Core">
|
|
<property name="logName" value="DAOLogger"/>
|
|
</object>
|
|
|
|
<object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data">
|
|
<property name="connectionstring">
|
|
<value>dsn=MyDSN;uid=sa;pwd=myPassword;</value>
|
|
</property>
|
|
</object>
|
|
|
|
<object name="appConfigPropertyOverride" type="Spring.Objects.Factory.Config.PropertyOverrideConfigurer, Spring.Core">
|
|
<property name="configSections">
|
|
<value>DaoConfigurationOverride</value>
|
|
</property>
|
|
</object>
|
|
|
|
</objects></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3 id="objects-variablesource">
|
|
<title>IVariableSource</title>
|
|
|
|
<para>The IVariableSource is the base interface for providing the
|
|
ability to get the value of property placeholders (name-value) pairs
|
|
from a variety of sources. Out of the box, Spring.NET supports a
|
|
number of variable sources that allow users to obtain variable values
|
|
from .NET config files, java-style property files, environment
|
|
variables, command line arguments and the registry and the new
|
|
connection strings configuration section in .NET 2.0. The list of
|
|
implementing classes is listed below. Please refer to the SDK
|
|
documentation for more information.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><classname>ConfigSectionVariableSource</classname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>PropertyFileVariableSource</classname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>EnvironmentVariableSource</classname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>CommandLineArgsVariableSource</classname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>RegistryVariableSource</classname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>SpecialFolderVariableSource</classname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>ConnectionStringsVariableSource</classname></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>You use this by defining an instance of
|
|
<classname>Spring.Objects.Factory.Config.VariablePlaceholderConfigurer</classname>
|
|
in your configuration and set the property
|
|
<literal>VariableSource</literal> to a single
|
|
<classname>IVariableSource</classname> instance or the list property
|
|
<literal>VariableSources</literal> to a list of
|
|
<classname>IVariableSource</classname> instances. In the case of the
|
|
same property defined in multiple
|
|
<classname>IVariableSource</classname> implementations, the first one
|
|
in the list that contains the property value will be used.
|
|
<programlisting><object type="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core">
|
|
<property name="VariableSources">
|
|
<list>
|
|
<object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core">
|
|
<property name="SectionNames" value="CryptedConfiguration" />
|
|
</object>
|
|
</list>
|
|
</property>
|
|
</object>
|
|
</programlisting>The IVariableSource interface is shown below</para>
|
|
|
|
<programlisting>public interface IVariableSource
|
|
{
|
|
string ResolveVariable(string name);
|
|
}</programlisting>
|
|
|
|
<para>This is a simple contract to implement if you should decide to
|
|
create your own custom implemention. Look at the source code of the
|
|
current implementations for some inspiration if you go that route. To
|
|
register your own custom implemenation, simply configure
|
|
VariablePlaceholderConfigurer to refer to your class.</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Customizing instantiation logic using
|
|
<literal>IFactoryObjects</literal></title>
|
|
|
|
<para>The <classname>Spring.Objects.Factory.IFactoryObject</classname>
|
|
interface is to be implemented by objects that <emphasis>are themselves
|
|
factories</emphasis>.</para>
|
|
|
|
<para>The <literal>IFactoryObject</literal> interface is a point of
|
|
pluggability into the Spring IoC containers instantiation logic. If you
|
|
have some complex initialization code that is better expressed in C# as
|
|
opposed to a (potentially) verbose amount of XML, you can create your
|
|
own <literal>IFactoryObject</literal>, write the complex initialization
|
|
inside that class, and then plug your custom
|
|
<literal>IFactoryObject</literal> into the container.</para>
|
|
|
|
<para>The <classname>IFactoryObject</classname> interface provides one
|
|
method and two (read-only) properties: <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>object GetObject()</literal>: has to return an
|
|
instance of the object this factory creates. The instance can
|
|
possibly be shared (depending on whether this factory provides
|
|
singletons or prototypes).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>bool IsSingleton</literal>: has to return
|
|
<literal>true</literal> if this IFactoryObject returns singletons,
|
|
<literal>false</literal> otherwise.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Type ObjectType</literal>: has to return either the
|
|
object type returned by the <methodname>GetObject()</methodname>
|
|
method or <literal>null</literal> if the type isn't known in
|
|
advance.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para><classname>IFactoryObject</classname></para>
|
|
|
|
<para>The IFactoryObject concept and interface is used in a number of
|
|
places within the Spring Framework. Some examples of its use is
|
|
described in <xref linkend="objects-advancedproperty-setting" /> for the
|
|
<classname>PropertyRetrievingFactoryObject</classname> and
|
|
<classname>FieldRetrievingFactoryObject</classname>. An additional use
|
|
of creating an custom IFactoryObject implementation is to retrieve an
|
|
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
|
|
actual <classname>IFactoryObject</classname> instance itself, not the
|
|
object it produces. This may be achieved by prepending the object id
|
|
with '<literal>&</literal>' (sans quotes) when calling the
|
|
<literal>GetObject</literal> method of the
|
|
<classname>IObjectFactory</classname> (including
|
|
<classname>IApplicationContext</classname>). So for a given
|
|
<classname>IFactoryObject</classname> with an id of
|
|
'<literal>myObject</literal>', invoking
|
|
<literal>GetObject("myObject")</literal> on the container will return
|
|
the product of the <classname>IFactoryObject</classname>, but invoking
|
|
<literal>GetObject("&myObject")</literal> will return the
|
|
<classname>IFactoryObject</classname> instance itself.</para>
|
|
|
|
<sect3>
|
|
<title>IConfigurableFactoryObject</title>
|
|
|
|
<para>The
|
|
<classname>Spring.Objects.Factory.IConfigurableFactoryObject</classname>
|
|
interface inherits from <classname>IFactoryObject</classname>
|
|
interface and adds the following property.<itemizedlist
|
|
spacing="compact">
|
|
<listitem>
|
|
<para><literal> IObjectDefinition ProductTemplate </literal>:
|
|
Gets the template object definition that should be used to
|
|
configure the instance of the object managed by this
|
|
factory.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para><classname>IConfigurableFactoryObject</classname> implementions
|
|
you already have examples of in <xref linkend="client-side" /> are
|
|
<classname>WebServiceProxyFactory</classname>.</para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="context-introduction">
|
|
<title>The <classname>IApplicationContext</classname></title>
|
|
|
|
<para>While the <literal>Spring.Objects</literal> namespace provides basic
|
|
functionality for managing and manipulating objects, often in a
|
|
programmatic way, the <literal>Spring.Context</literal> namespace
|
|
introduces the <classname>IApplicationContext</classname> interface, which
|
|
enhances the functionality provided by the
|
|
<classname>IObjectFactory</classname> interface in a more
|
|
<emphasis>framework-oriented style</emphasis>. Many users will use
|
|
ApplicationContext in a completely declarative fashion, not even having to
|
|
create it manually, but instead relying on support classes such as the
|
|
.NET configuration section handlers such as ContextHandler and
|
|
WebContextHandler together to declaratively define the ApplicationContext
|
|
and retrieve it though a ContextRegistry. (Of course it is still possible
|
|
to create an <classname>IApplicationContext</classname>
|
|
Programatically).</para>
|
|
|
|
<para>The basis for the context module is the
|
|
<classname>IApplicationContext</classname> interface, located in the
|
|
<literal>Spring.Context</literal> namespace. Deriving from the
|
|
<classname>IObjectFactory</classname> interface, it provides all the
|
|
functionality of the <classname>IObjectFactory</classname>. To be able to
|
|
work in a more framework-oriented fashion, using layering and hierarchical
|
|
contexts, the <literal>Spring.Context</literal> namespace also provides
|
|
the following functionality<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><emphasis>Loading of multiple (hierarchical)
|
|
contexts</emphasis>, allowing some of them to be focused and used on
|
|
one particular layer, for example the web layer of an
|
|
application.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Access to localized resources</emphasis> at the
|
|
application level by implementing
|
|
<classname>IMessageSource</classname>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Uniform access to resources</emphasis> that can be
|
|
read in as an InputStream, such as URLs and files by implementing
|
|
<classname>IResourceLoader</classname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Loosely Coupled Event Propagation</emphasis>.
|
|
Publishers and subscribers of events do not have to be directly
|
|
aware of each other as they register their interest indirectly
|
|
through the application context.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<sect2>
|
|
<title>IObjectFactory or IApplicationContext?</title>
|
|
|
|
<para>Short version: use an
|
|
<emphasis><classname>IApplicationContext</classname></emphasis> unless
|
|
you have a really good reason for not doing so. For those of you that
|
|
are looking for slightly more depth as to the 'but why' of the above
|
|
recommendation, keep reading.</para>
|
|
|
|
<para>As the <classname>IApplicationContext</classname> includes all the
|
|
functionality the object factory via its inheritance of the
|
|
<classname>IObjectFactory</classname> interface, it is generally
|
|
recommended to be used over the <classname>IObjectFactory</classname>
|
|
except for a few limited situations where memory consumption might be
|
|
critical. This may become more important if the .NET Compact Framework
|
|
is supported. The history of <classname>IObjectFactory</classname> comes
|
|
from the Spring Java framework, where the use of Spring in Applets was a
|
|
concern to reduce memory consumption. However, for most 'typical'
|
|
enterprise applications and systems, the
|
|
<classname>IApplicationContext</classname> is what you will want to use.
|
|
Spring generally makes heavy use of the
|
|
<classname>IObjectPostProcessor</classname> extension point (to effect
|
|
proxying and suchlike), and if you are using just a plain
|
|
<classname>IObjectFactory</classname> then a fair amount of support such
|
|
as transactions and AOP will not take effect (at least not without some
|
|
extra steps on your part), which could be confusing because nothing will
|
|
actually be wrong with the configuration.</para>
|
|
|
|
<para>Find below a feature matrix that lists what features are provided
|
|
by the <classname>IObjectFactory</classname> and
|
|
<classname>IApplicationContext</classname> interfaces (and attendant
|
|
implementations). The following sections describe functionality that
|
|
<classname>IApplicationContext</classname> adds to the basic
|
|
<classname>IObjectFactory</classname> capabilities in a lot more depth
|
|
than the said feature matrix.)</para>
|
|
|
|
<table id="context-introduction-ctx-vs-objectfactory-feature-matrix"
|
|
pgwide="1">
|
|
<title>Feature Matrix</title>
|
|
|
|
<tgroup cols="3">
|
|
<colspec align="left" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry align="center">Feature</entry>
|
|
|
|
<entry
|
|
align="center"><interfacename>IObjectFactory</interfacename></entry>
|
|
|
|
<entry
|
|
align="center"><interfacename>IApplicationContext</interfacename></entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><para>Object instantiation/wiring</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Automatic
|
|
<interfacename>IObjectPostProcessor</interfacename>
|
|
registration</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Automatic
|
|
<interfacename>IObjectFactoryPostProcessor</interfacename>
|
|
registration</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Convenient
|
|
<interfacename>IMessageSource</interfacename>
|
|
access</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para><interfacename>ApplicationEvent</interfacename>
|
|
publication</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>Singleton service locator style access</entry>
|
|
|
|
<entry align="center">No</entry>
|
|
|
|
<entry align="center">Yes</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>Declarative registration of custom resource protocol
|
|
handler, XML Parsers for object definitions, and type
|
|
aliases</entry>
|
|
|
|
<entry align="center">No</entry>
|
|
|
|
<entry align="center">Yes</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="context-configuration">
|
|
<title>Configuration of IApplicationContext</title>
|
|
|
|
<para>Well known locations in the .NET application configuration file are
|
|
used to register resource handlers, custom parsers, type alias, and custom
|
|
type converts in addition to the context and objects sections mentioned
|
|
previously. A sample .NET application configuration file showing all these
|
|
features is shown below. Each section requires the use of a custom
|
|
configuration section handler. Note that the types shown for resource
|
|
handlers and parsers are fictional. <programlisting><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
|
|
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
|
|
<section name="resources" type="Spring.Context.Support.<classname>ResourceHandlersSectionHandler</classname>, Spring.Core"/>
|
|
<section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/>
|
|
<section name="typeConverters" type="Spring.Context.Support.TypeConvertersSectionHandler, Spring.Core"/>
|
|
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
<parsers>
|
|
<parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
|
|
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
|
|
</parsers>
|
|
|
|
<resources>
|
|
<handler protocol="db" type="MyCompany.MyApp.Resources.MyDbResource"/>
|
|
</resources>
|
|
|
|
<context caseSensitive="false">
|
|
<resource uri="config://spring/objects"/>
|
|
<resource uri="db://user:pass@dbName/MyDefinitionsTable"/>
|
|
</context>
|
|
|
|
<typeAliases>
|
|
<alias name="WebServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web"/>
|
|
<alias name="DefaultPointcutAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/>
|
|
<alias name="AttributePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop"/>
|
|
<alias name="CacheAttribute" type="Spring.Attributes.CacheAttribute, Spring.Core"/>
|
|
<alias name="MyType" type="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/>
|
|
</typeAliases>
|
|
|
|
<typeConverters>
|
|
<converter for="Spring.Expressions.IExpression, Spring.Core" type="Spring.Objects.TypeConverters.ExpressionConverter, Spring.Core"/>
|
|
<converter for="MyTypeAlias" type="MyCompany.MyProject.Converters.MyTypeConverter, MyAssembly"/>
|
|
</typeConverters>
|
|
|
|
<objects xmlns="http://www.springframework.net">
|
|
...
|
|
</objects>
|
|
|
|
</spring>
|
|
|
|
</configuration>
|
|
</programlisting> The new sections are described below. The attribute
|
|
<literal>caseSensitive</literal> allows the for both
|
|
<classname>IObjectFactory</classname> and
|
|
<classname>IApplicationContext</classname> implementations to not pay
|
|
attention to the case of the object names. This is important in web
|
|
applications so that ASP.NET pages can be resolved in a case independent
|
|
manner. The default value is true.</para>
|
|
|
|
<sect2 id="context-custom-parsers">
|
|
<title>Registering custom parsers</title>
|
|
|
|
<para>Instead of using the default XML schema that is generic in nature
|
|
to define an object's properties and dependencies, you can create your
|
|
own XML schema specific to an application domain. This has the benefit
|
|
of being easier to type and getting XML intellisense for the schema
|
|
being used. The downside is that you need to write code that will
|
|
transform this XML into Spring object definitions. One would typically
|
|
implement a custom parser by deriving from the class
|
|
<classname>ObjectsNamespaceParser</classname> and overriding the methods
|
|
<literal> int ParseRootElement(XmlElement root, XmlResourceReader
|
|
reader)</literal> and <literal>int ParseElement(XmlElement element,
|
|
XmlResourceReader reader)</literal>. Registering custom parsers outside
|
|
of App.config will be addressed in a future release.</para>
|
|
|
|
<para>To register a custom parser register a section handler of the type
|
|
<literal>Spring.Context.Support.NamespaceParsersSectionHandler</literal>
|
|
in the configSecitons section of App.config. The parser configuration
|
|
section contains one or more <parser> elements each with a type
|
|
attribute. Below is an example that registers all the namespaces
|
|
provided in Spring.</para>
|
|
|
|
<programlisting><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<!-- other configuration section handler defined here -->
|
|
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
<parsers>
|
|
<parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
|
|
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
|
|
<parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" />
|
|
<parser type="Spring.Validation.Config.ValidationNamespaceParser, Spring.Core" />
|
|
<parser type="Spring.Remoting.Config.RemotingNamespaceParser, Spring.Services" />
|
|
</parsers>
|
|
</spring>
|
|
|
|
</configuration></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 id="context-custom-resourcehandler">
|
|
<title>Registering custom resource handlers</title>
|
|
|
|
<para>Creating a custom resource handler means implementing the
|
|
<classname>IResource</classname> interface. The base class
|
|
<classname>AbstractResource</classname> is a useful starting point. Look
|
|
at the Spring source for classes such as
|
|
<classname>FileSystemResource</classname> or
|
|
<classname>AssemblyResource</classname> for implementation tips. You can
|
|
register your custom resource handler either within App.config, as shown
|
|
in the program listing at the start of this section using a
|
|
.<classname>ResourceHandlersSectionHandler</classname> or define an
|
|
object of the type
|
|
<classname>Spring.Objects.Factory.Config.ResourceHandlerConfigurer</classname>
|
|
as you would any other Spring managed object. An example of the latter
|
|
is shown below:</para>
|
|
|
|
<programlisting><object id="myResourceHandlers" type="Spring.Objects.Factory.Config.<classname>ResourceHandlersSectionHandler</classname>, Spring.Core">
|
|
<property name="ResourceHandlers">
|
|
<dictionary>
|
|
<entry key="db" value="MyCompany.MyApp.Resources.MyDbResource, MyAssembly"/>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 id="context-type-alias">
|
|
<title>Registering Type Aliases</title>
|
|
|
|
<para>Type aliases allow you to simplify Spring configuration file by
|
|
replacing fully qualified type name with an alias for frequently used
|
|
types. Aliases can be registered both within a config file and
|
|
programatically and can be used anywhere in the context config file
|
|
where a fully qualified type name is expected. Type aliases can also be
|
|
defined for generic types.</para>
|
|
|
|
<para>One way to configure a type alias is to define them in a custom
|
|
config section in the Web/App.config file for your application, as well
|
|
as the custom configuration section handler. See the previous XML
|
|
configuration listing for an example that makes an alias for the
|
|
WebServiceExporter type. Once you have aliases defined, you can simply
|
|
use them anywhere where you would normally specify a fully qualified
|
|
type name:<programlisting>
|
|
<object id="MyWebService" type="WebServiceExporter">
|
|
...
|
|
</object>
|
|
|
|
<object id="cacheAspect" type="DefaultPointcutAdvisor">
|
|
<property name="Pointcut">
|
|
<object type="AttributePointcut">
|
|
<property name="Attribute" value="CacheAttribute"/>
|
|
</object>
|
|
</property>
|
|
<property name="Advice" ref="aspNetCacheAdvice"/>
|
|
</object></programlisting></para>
|
|
|
|
<para>To register a type alias register a section handler of the type
|
|
<literal>Spring.Context.Support.TypeAliasesSectionHandler</literal> in
|
|
the configSecitons section of App.config. The type alias configuration
|
|
section contains one or more <alias> elements each with a name and
|
|
a type attribute. Below is an example that registers the alias for
|
|
WebServiceExporter </para>
|
|
|
|
<programlisting><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<!-- other configuration section handler defined here -->
|
|
<section name="parsers" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
<typeAliases>
|
|
<alias name="WebServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web"/>
|
|
</typeAliases>
|
|
</spring>
|
|
|
|
</configuration></programlisting>
|
|
|
|
<para> For an example showing type aliases for generic types see <xref
|
|
linkend="objects-creation-generic-types" />.</para>
|
|
|
|
<para>Another way is to define an object of the type
|
|
<classname>Spring.Objects.Factory.Config.TypeAliasConfigurer</classname>
|
|
within the regular <objects> section of any standard Spring
|
|
configuration file. This approach allows for more modularity in defining
|
|
type aliases, for example if you can't access App.config/Web.config. An
|
|
example of registration using a
|
|
<classname>TypeAliasConfigurer</classname> is shown below</para>
|
|
|
|
<programlisting><object id="myTypeAlias" type="Spring.Objects.Factory.Config.TypeAliasConfigurer, Spring.Core">
|
|
<property name="TypeAliases">
|
|
<dictionary>
|
|
<entry key="WebServiceExporter" value="Spring.Web.Services.WebServiceExporter, Spring.Web"/>
|
|
<entry key="DefaultPointcutAdvisor" value="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/>
|
|
<entry key="MyType" value="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 id="context-type-converters">
|
|
<title>Registering Type Converters</title>
|
|
|
|
<para>The standard .NET mechanism for specifying a type converter is to
|
|
add a <classname>TypeConverter</classname> attribute to a type
|
|
definition to specify the type of the Converter. This is the preferred
|
|
way of defining type converters if you control the source code for the
|
|
type that you want to define a converter for. However, this
|
|
configuration section allows you to specify converters for the types
|
|
that you don't control, and it also allows you to override some of the
|
|
standard type converters, such as the ones that are defined for some of
|
|
the types in the .NET Base Class Library.</para>
|
|
|
|
<para>You can specify the type converters in App.config by using
|
|
Spring.Context.Support.TypeConvertersSectionHandler as shown before or
|
|
define an object of the type
|
|
<classname>Spring.Objects.Factory.Config.</classname><classname>CustomConverterConfigurer</classname>.
|
|
An example of registration using a
|
|
<classname>CustomConverterConfigurer</classname> is shown below</para>
|
|
|
|
<programlisting><object id="myTypeConverters" type="Spring.Objects.Factory.Config.CustomConverterConfigurer, Spring.Core">
|
|
<property name="CustomConverters">
|
|
<dictionary>
|
|
<entry key="System.Date" value="MyCompany.MyProject.MyNamespace.MyCustomDateConverter, MyAssembly"/>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="context-functionality">
|
|
<title>Added functionality of the
|
|
<classname>IApplicationContext</classname></title>
|
|
|
|
<para>As already stated in the previous section, the
|
|
<classname>IApplicationContext</classname> has a couple of features that
|
|
distinguish it from the <classname>IObjectFactory</classname>. Let us
|
|
review them one-by-one.</para>
|
|
|
|
<sect2 id="context-functionality-hierarchy">
|
|
<title>Context Hierarchies</title>
|
|
|
|
<para>You can structure the configuration information of application
|
|
context into hierarchies that naturally reflect the internal layering of
|
|
your application. As an example, abstract object definitions may appear
|
|
in a parent application context configuration file, possibly as an
|
|
embedded assembly resource so as not to invite accidental changes.
|
|
<programlisting><spring>
|
|
<context>
|
|
<resource uri="assembly://MyAssembly/MyProject/root-objects.xml"/>
|
|
<context name="mySubContext">
|
|
<resource uri="file://objects.xml"/>
|
|
</context>
|
|
</context>
|
|
</spring></programlisting> The nesting of <literal>context</literal>
|
|
elements reflects the parent-child hierarchy you are creating. The
|
|
nesting can be to any level though it is unlikely one would need a deep
|
|
application hierarchy. The xml file must contain the
|
|
<literal><objects></literal> as the root name. Another example of
|
|
a hierarchy, but using sections in the application configuration file is
|
|
shown below. <programlisting><configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
<sectionGroup name="child">
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
</sectionGroup>
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
|
|
<context name="ParentContext">
|
|
<resource uri="config://spring/objects"/>
|
|
<context name="ChildContext">
|
|
<resource uri="config://spring/child/objects"/>
|
|
</context>
|
|
</context>
|
|
|
|
<objects xmlns="http://www.springframework.net">
|
|
|
|
...
|
|
|
|
</objects>
|
|
|
|
<child>
|
|
<objects xmlns="http://www.springframework.net">
|
|
|
|
...
|
|
|
|
</objects>
|
|
</child>
|
|
|
|
</spring></programlisting></para>
|
|
|
|
<para>As a reminder, the <literal>type</literal> attribute of the
|
|
context tag is optional and defaults to
|
|
<classname>Spring.Context.Support.XmlApplicationContext</classname>. The
|
|
name of the context can be used in conjunction with the service locator
|
|
class, <classname>ContextRegistry</classname>, discussed in <xref
|
|
linkend="objects-servicelocator" /></para>
|
|
</sect2>
|
|
|
|
<sect2 id="context-functionality-messagesource">
|
|
<title>Using <literal>IMessageSource</literal></title>
|
|
|
|
<para>The <classname>IApplicationContext</classname> interface extends
|
|
an interface called <classname>IMessageSource</classname> and provides
|
|
localization (i18n or internationalization) services for text messages
|
|
and other resource data types such as images. This functionality makes
|
|
it easier to use .NET's localization features at an application level
|
|
and also offers some performance enhancements due to caching of
|
|
retrieved resources. Together with the
|
|
<literal>NestingMessageSource</literal>, capable of hierarchical message
|
|
resolving, these are the basic interfaces Spring.NET provides for
|
|
localization. Let's quickly review the methods defined there:
|
|
<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name)</literal>: retrieves
|
|
a message from the <classname>IMessageSource</classname> and using
|
|
CurrentUICulture.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, CultureInfo
|
|
cultureInfo)</literal>: retrieves a message from the
|
|
<classname>IMessageSource</classname> using a specified
|
|
culture.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, params object[]
|
|
args)</literal>: retrieves a message from the
|
|
<classname>IMessageSource</classname> using a variable list of
|
|
arguments as replacement values in the message. The
|
|
CurrentUICulture is used to resolve the message.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, CultureInfo
|
|
cultureInfo, params object[] args)</literal>: retrieves a message
|
|
from the <classname>IMessageSource</classname> using a variable
|
|
list of arguments as replacement values in the message. The
|
|
specified culture is used to resolve the message.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, string
|
|
defaultMessage, CultureInfo culture, params object[]
|
|
arguments)</literal>: retrieves a message from the
|
|
<classname>IMessageSource</classname> using a variable list of
|
|
arguments as replacement values in the message. The specified
|
|
culture is used to resolve the message. If no message can be
|
|
resolved, the default message is used.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(IMessageSourceResolvable
|
|
resolvable, <classname>CultureInfo</classname> culture)
|
|
</literal>: all properties used in the methods above are also
|
|
wrapped in a class - the
|
|
<literal>MessageSourceResolvable</literal>, which you can use in
|
|
this method.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>object GetResourceObject(string name)</literal>:Get
|
|
a localized resource object, i.e. Icon, Image, etc. given the
|
|
resource name. The CurrentUICulture is used to resolve the
|
|
resource object.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>object GetResourceObject(string name, CultureInfo
|
|
cultureInfo)</literal>:Get a localized resource object, i.e. Icon,
|
|
Image, etc. given the resource name. The specified culture is used
|
|
to resolve the resource object.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void ApplyResources(object value, string
|
|
objectName, CultureInfo cultureInfo)</literal>: Uses a
|
|
ComponentResourceManager to apply resources to all object
|
|
properties that have a matching key name. Resource key names are
|
|
of the form objectName.propertyName</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>When an <classname>IApplicationContext</classname> gets loaded, it
|
|
automatically searches for an <classname>IMessageSource</classname>
|
|
object defined in the context. The object has to have the name
|
|
<literal>messageSource</literal>. If such an object is found, all calls
|
|
to the methods described above will be delegated to the message source
|
|
that was found. If no message source was found, the
|
|
<classname>IApplicationContext</classname> checks to see if it has a
|
|
parent containing a similar object, with a similar name. If so, it uses
|
|
that object as the <classname>IMessageSource</classname>. If it can't
|
|
find any source for messages, an empty
|
|
<literal>StaticMessageSource</literal> will be instantiated in order to
|
|
be able to accept calls to the methods defined above.</para>
|
|
|
|
<warning>
|
|
|
|
|
|
<title>Fallback behavior</title>
|
|
|
|
The fallback rules for localized resources seem to have a bug that is fixed by applying Service Pack 1 for .NET 1.1. This affects the use of IMessageSource.GetMessage methods that specify CultureInfo. The core of the issue in the .NET BCL is the method ResourceManager.GetObject that accepts CultureInfo. .
|
|
</warning>
|
|
|
|
<para>Spring.NET provides two <classname>IMessageSource</classname>
|
|
implementations. These are
|
|
<classname>ResourceSetMessageSource</classname> and
|
|
<classname>StaticMessageSource</classname>. Both implement
|
|
<classname>IHierarchicalMessageSource</classname> to resolve messages
|
|
hierarchically. The <classname>StaticMessageSource</classname> is hardly
|
|
ever used but provides programmatic ways to add messages to the source.
|
|
The <classname>ResourceSetMessageSource</classname> is more interesting
|
|
and an example is provided for in the distribution and discussed more
|
|
extensively in the <xref linkend="quickstarts" /> section. The
|
|
<classname>ResourceSetMessageSource</classname> is configured by
|
|
providing a list of <classname>ResourceManager</classname>s. When a
|
|
message code is to be resolved, the list of ResourceManagers is searched
|
|
to resolve the code. For each <classname>ResourceManager</classname> a
|
|
<classname>ResourceSet</classname> is retrieved and asked to resolve the
|
|
code. Note that this search does not replace the standard hub-and-spoke
|
|
search for localized resources. The ResourceManagers list specifies the
|
|
multiple 'hubs' where the standard search starts. <programlisting><object name="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core">
|
|
<property name="resourceManagers">
|
|
<list>
|
|
<value>Spring.Examples.AppContext.MyResource, Spring.Examples.AppContext</value>
|
|
</list>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<para>You can specify the arguments to construct a ResourceManager as a
|
|
two part string value containing the base name of the resource and the
|
|
assembly name. This will be converted to a ResourceManager via the
|
|
<classname>ResourceManagerConverter</classname> TypeConverter. This
|
|
converter can be similarly used to set a property on any object that is
|
|
of the type <classname>ResourceManager.</classname> You may also specify
|
|
an instance of the <classname>ResourceManager</classname> to use via an
|
|
object reference. The convenience class
|
|
<classname>Spring.Objects.Factory.Config.ResourceManagerFactoryObject</classname>
|
|
can be used to conveniently create an instance of a ResourceManager.
|
|
<programlisting><object name="myResourceManager" type="Spring.Objects.Factory.Config.ResourceManagerFactoryObject, Spring.Core">
|
|
<property name="baseName">
|
|
<value>Spring.Examples.AppContext.MyResource</value>
|
|
</property>
|
|
<property name="assemblyName">
|
|
<value>Spring.Examples.AppContext</value>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<para>In application code, a call to <literal>GetMessage</literal> will
|
|
retrieve a properly localized message string based on a code value. Any
|
|
arguments present in the retrieved string are replaced using
|
|
<classname>String.Format</classname> semantics. The ResourceManagers,
|
|
ResourceSets and retrieved strings are cached to provide quicker lookup
|
|
performance. The key 'HelloMessage' is contained in the resource file
|
|
with a value of <literal>Hello {0} {1}</literal>. The following call on
|
|
the application context will return the string <literal>Hello Mr.
|
|
Anderson</literal>. <emphasis>Note</emphasis> that the caching of
|
|
ResourceSets is via the concatenation of the ResourceManager base name
|
|
and the CultureInfo string. This combination must be unique.
|
|
<programlisting>string msg = ctx.GetMessage("HelloMessage",
|
|
new object[] {"Mr.", "Anderson"},
|
|
CultureInfo.CurrentCulture );
|
|
</programlisting></para>
|
|
|
|
<para>It is possible to chain the resolution of messages by passing
|
|
arguments that are themselves messages to be resolved giving you greater
|
|
flexibility in how you can structure your message resolution. This is
|
|
achieved by passing as an argument a class that implements
|
|
<literal>IMessageResolvable</literal> instead of a string literal. The
|
|
convenience class <classname>DefaultMessageResolvable</classname> is
|
|
available for this purpose. As an example if the resource file contains
|
|
a key name <literal>error.required</literal> that has the value
|
|
'<literal>{0} is required {1}</literal>' and another key name
|
|
<literal>field.firstname</literal> with the value '<literal>First
|
|
name</literal>'. The following code will create the string
|
|
'<literal>First name is required dude!</literal>' <programlisting>string[] codes = {"field.firstname"};
|
|
DefaultMessageResolvable dmr = new DefaultMessageResolvable(codes, null);
|
|
ctx.GetMessage("error.required",
|
|
new object[] { dmr, "dude!" },
|
|
CultureInfo.CurrentCulture ));
|
|
</programlisting></para>
|
|
|
|
<para>The examples directory in the distribution contains an example
|
|
program, <literal>Spring.Examples.AppContext</literal>, that
|
|
demonstrates usage of these features.</para>
|
|
|
|
<para>The <classname>IMessageSourceAware</classname> interface can also
|
|
be used to acquire a reference to any
|
|
<classname>IMessageSource</classname> that has been defined. Any object
|
|
that is defined in an <classname>IApplicationContext</classname> that
|
|
implements the <classname>IMessageSourceAware</classname> interface will
|
|
be injected with the application context's
|
|
<classname>IMessageSource</classname> when it (the object) is being
|
|
created and configured.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="context-functionality-resources">
|
|
<title>Using resources within Spring.NET</title>
|
|
|
|
<para>A lot of applications need to access resources. Resources here,
|
|
might mean files, but also news feeds from the Internet or normal web
|
|
pages. Spring.NET provides a clean and transparent way of accessing
|
|
resources in a protocol independent way. The
|
|
<classname>IApplicationContext</classname> has a method
|
|
(<literal>GetResource(string)</literal>) to take care of this. Refer to
|
|
<xref linkend="objects-iresource" /> for more information on the string
|
|
format to use and the <classname>IResource</classname> abstraction in
|
|
general.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="context-functionality-pubsub">
|
|
<title>Loosely coupled events</title>
|
|
|
|
<para>The Eventing Registry allows developers to utilize a loosely
|
|
coupled event wiring mechanism. By decoupling the event publication and
|
|
the event subscription, most of the mundane event wiring is handled by
|
|
the IoC container. Event publishers can publish their event to a central
|
|
registry, either all of their events or a subset based on criteria such
|
|
as delegate type, name, return value, etc... Event subscribers can
|
|
choose to subscribe to any number of published events. Subscribers can
|
|
subscriber to events based on the type of object exposing them, allowing
|
|
one subscriber to handle all events of a certain type without regards to
|
|
how many different instances of that type are created.</para>
|
|
|
|
<para>The <classname>Spring.Objects.Events.IEventRegistry</classname>
|
|
interface represents the central registry and defines publish and
|
|
subscribe methods. <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>void PublishEvents( object sourceObject
|
|
)</literal>: publishes all events of the source object to
|
|
subscribers that implement the correct handler methods.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void Subscribe(object subscriber )</literal>: The
|
|
subscriber receives all events from the source object for which it
|
|
has matching handler methods.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void Subscribe(object subscriber, Type
|
|
targetSourceType )</literal>: The subscriber receives all events
|
|
from a source object of a particular type for which it has
|
|
matching handler methods.</para>
|
|
</listitem>
|
|
</itemizedlist> <classname>IApplicationContext</classname> implements
|
|
this interface and delegates the implementation to an instance of
|
|
<classname>Spring.Objects.Events.Support.EventRegistry</classname>. You
|
|
are free to create and use as many EventRegistries as you like but since
|
|
it is common to use only one in an application,
|
|
<classname>IApplicationContext</classname> provides convenient access to
|
|
a single instance.</para>
|
|
|
|
<para>Within the
|
|
<literal>example/Spring/Spring.Examples.EventRegistry</literal>
|
|
directory you will find an example on how to use this functionality.
|
|
When you open up the project, the most interesting file is the
|
|
EventRegistryApp.cs file. This application loads a set of object
|
|
definitions from the application configuration file into an
|
|
<classname>IApplicationContext</classname> instance. From there, three
|
|
objects are loaded up: one publisher and two subscribers. The publisher
|
|
publishes its events to the <classname>IApplicationContext</classname>
|
|
instance: <programlisting>// Create the Application context using configuration file
|
|
IApplicationContext ctx = ContextRegistry.GetContext();
|
|
|
|
// Gets the publisher from the application context
|
|
MyEventPublisher publisher = (MyEventPublisher)ctx.GetObject("MyEventPublisher");
|
|
|
|
// Publishes events to the context.
|
|
ctx.PublishEvents( publisher );
|
|
</programlisting> One of the two subscribers subscribes to all events
|
|
published to the <classname>IApplicationContext</classname> instance,
|
|
using the publisher type as the filter criteria.<programlisting>// Gets first instance of subscriber
|
|
MyEventSubscriber subscriber = (MyEventSubscriber)ctx.GetObject("MyEventSubscriber");
|
|
|
|
// Gets second instance of subscriber
|
|
MyEventSubscriber subscriber2 = (MyEventSubscriber)ctx.GetObject("MyEventSubscriber");
|
|
|
|
// Subscribes the first instance to the any events published by the type MyEventPublisher
|
|
ctx.Subscribe( subscriber, typeof(MyEventPublisher) );</programlisting> This
|
|
will wire the first subscriber to the original event publisher. Anytime
|
|
the event publisher fires an event,
|
|
(<literal>publisher.ClientMethodThatTriggersEvent1();</literal>) the
|
|
first subscriber will handle the event, but the second subscriber will
|
|
not. This allows for selective subscription, regardless of the original
|
|
prototype definition.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="context-functionality-events">
|
|
<title>Event notification from
|
|
<classname>IApplicationContext</classname></title>
|
|
|
|
<para>Event handling in the <classname>IApplicationContext</classname>
|
|
is provided through the <classname>IApplicationListener</classname>
|
|
interface that contains the single method <literal>void
|
|
OnApplicationEvent( object source, ApplicationEventArgs
|
|
applicationEventArgs )</literal>. Classes that implement the
|
|
<classname>IApplicationListener</classname> interface are automatically
|
|
registered as a listener with the
|
|
<classname>IApplicationContext</classname>. Publishing an event is done
|
|
via the context's <literal>PublishEvent( ApplicationEventArgs eventArgs
|
|
)</literal> method. This implementation is based on the traditional
|
|
<emphasis>Observer</emphasis> design pattern.</para>
|
|
|
|
<para>The event argument type,
|
|
<classname>ApplicationEventArgs</classname>, adds the time of the event
|
|
firing as a property. The derived class
|
|
<classname>ContextEventArgs</classname> is used to notify observers on
|
|
the lifecycle events of the application context. It contains a property
|
|
<literal>ContextEvent Event</literal> that returns the enumeration
|
|
<literal>Refreshed</literal> or <literal>Closed.</literal>. The
|
|
<literal>Refreshed</literal> enumeration value indicated that the
|
|
<classname>IApplicationContext</classname> was either initialized or
|
|
refreshed. Initialized here means that all objects are loaded,
|
|
singletons are pre-instantiated and the
|
|
<classname>IApplicationContext</classname> is ready for use. The
|
|
<literal>Closed</literal> is published when the
|
|
<classname>IApplicationContext</classname> is closed using the
|
|
<literal>Dispose()</literal> method on the
|
|
<classname>IConfigurableApplicationContext</classname> interface. Closed
|
|
here means that singletons are destroyed.</para>
|
|
|
|
<para>Implementing custom events can be done as well. Simply call the
|
|
<literal>PublishEvent</literal> method on the
|
|
<classname>IApplicationContext</classname>, specifying a parameter which
|
|
is an instance of your custom event argument subclass.</para>
|
|
|
|
<para>Let's have a look at an example. First, the
|
|
<classname>IApplicationContext</classname>: <programlisting><object id="emailer" type="Example.EmailObject">
|
|
<property name="blackList">
|
|
<list>
|
|
<value>black@list.org</value>
|
|
<value>white@list.org</value>
|
|
<value>john@doe.org</value>
|
|
</list>
|
|
</property>
|
|
</object>
|
|
|
|
<object id="blackListListener" type="Example.BlackListNotifier">
|
|
<property name="notificationAddress">
|
|
<value>spam@list.org</value>
|
|
</property>
|
|
</object></programlisting> and then, the actual objects:
|
|
<programlisting>public class EmailObject : IApplicationContextAware {
|
|
|
|
// the blacklist
|
|
private IList blackList;
|
|
|
|
public IList BlackList
|
|
{
|
|
set { this.blackList = value; }
|
|
}
|
|
|
|
public IApplicationContext ApplicationContext
|
|
{
|
|
set { this.ctx = value; }
|
|
}
|
|
|
|
public void SendEmail(string address, string text) {
|
|
if (blackList.contains(address))
|
|
{
|
|
BlackListEvent evt = new BlackListEvent(address, text);
|
|
ctx.publishEvent(evt);
|
|
return;
|
|
}
|
|
// send email...
|
|
}
|
|
}
|
|
|
|
public class BlackListNotifier : IApplicationListener
|
|
{
|
|
|
|
// notification address
|
|
private string notificationAddress;
|
|
|
|
public string NotificationAddress
|
|
{
|
|
set { this.notificationAddress = value; }
|
|
}
|
|
|
|
public void OnApplicationEvent(ApplicationEvent evt)
|
|
{
|
|
if (evt instanceof BlackListEvent)
|
|
{
|
|
// notify appropriate person
|
|
}
|
|
}
|
|
}</programlisting></para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="objects-context-customization">
|
|
<title>Customized behavior in the ApplicationContext</title>
|
|
|
|
<para>The <classname>IObjectFactory</classname> already offers a number of
|
|
mechanisms to control the lifecycle of objects deployed in it (such as
|
|
marker interfaces like <classname>IInitializingObject</classname> and
|
|
<classname>System.IDisposable</classname>, their configuration only
|
|
equivalents such as <literal>init-method</literal> and
|
|
<literal>destroy-method</literal>) attributes in an XmlObjectFactory
|
|
configuration, and object post-processors. In an
|
|
<classname>IApplicationContext</classname>, all of these still work, but
|
|
additional mechanisms are added for customizing behavior of objects and
|
|
the container.</para>
|
|
|
|
<sect2 id="objects-context-applicationcontextaware">
|
|
<title>The <literal>IApplicationContextAware</literal> marker
|
|
interface</title>
|
|
|
|
<para>All marker interfaces available with ObjectFactories still work.
|
|
The <classname>IApplicationContext</classname> does add one extra marker
|
|
interface which objects may implement,
|
|
<literal>IApplicationContextAware</literal>. An object which implements
|
|
this interface and is deployed into the context will be called back on
|
|
creation of the object, using the interface's
|
|
<literal>ApplicationContext</literal> property, and provided with a
|
|
reference to the context, which may be stored for later interaction with
|
|
the context.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-context-objectpostprocessor">
|
|
<title>The <literal>IObjectPostProcessor</literal></title>
|
|
|
|
<para>Object post-processors are classes which implement the
|
|
<classname>Spring.Objects.Factory.Config.IObjectPostProcessor</classname>
|
|
interface, have <link
|
|
linkend="objects-factory-customizing">already</link> been mentioned. It
|
|
is worth mentioning again here though, that post-processors are much
|
|
more convenient to use in <classname>IApplicationContext</classname>s
|
|
than in plain <classname>IObjectFactory</classname> instances. In an
|
|
<classname>IApplicationContext</classname>, any deployed object which
|
|
implements the above marker interface is automatically detected and
|
|
registered as an object post-processor, to be called appropriately at
|
|
creation time for each object in the factory.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-context-objectfactorypostprocessor">
|
|
<title>The <literal>IObjectFactoryPostProcessor</literal></title>
|
|
|
|
<para>Object factory post-processors are classes which implement the
|
|
<classname>Spring.Objects.Factory.Config.IObjectFactoryPostProcessor</classname>
|
|
interface, have <link
|
|
linkend="objects-factory-customizing-factory-postprocessors">already</link>
|
|
been mentioned. It is worth mentioning again here though, that object
|
|
factory post-processors are much more convenient to use in
|
|
<classname>IApplicationContext</classname>s. In an
|
|
<classname>IApplicationContext</classname>, any deployed object which
|
|
implements the above marker interface is automatically detected as an
|
|
object factory post-processor, to be called at the appropriate
|
|
time.</para>
|
|
</sect2>
|
|
|
|
<sect2 id="objects-context-placeholderconfigurer">
|
|
<title>The <literal>PropertyPlaceholderConfigurer</literal></title>
|
|
|
|
<para>The <literal>PropertyPlaceholderConfigurer</literal> has <link
|
|
linkend="objects-factory-placeholderconfigurer">already</link> been
|
|
described in the context of its use within an
|
|
<classname>IObjectFactory</classname>. It is worth mentioning here
|
|
though, that it is generally more convenient to use it with an
|
|
<classname>IApplicationContext</classname>, since the context will
|
|
automatically recognize and apply any object factory post-processors,
|
|
such as this one, when they are simply deployed into it like any other
|
|
object. There is no need for a manual step to execute it.</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Configuration of ApplicationContext without using XML</title>
|
|
|
|
<para>The class GenericApplicationContext can be used as a basis for
|
|
creating an IApplicationContext implementation that read the container
|
|
metadata from sources other than XML. This could be by scanning objects in
|
|
a .DLL for known attributes or a scripting language that leverages a DSL
|
|
to create terse IObjectDefinitions. There is a class,
|
|
Spring.Objects.Factory.Support.ObjectDefinitionBuilder offers some
|
|
convenience methods for creating an IObjectDefinition in a less verbose
|
|
manner than using the RootObjectDefinition API. The following shows how to
|
|
configure the GenericApplicationContext to read from XML, just so show
|
|
familiar API usage</para>
|
|
|
|
<programlisting>GenericApplicationContext ctx = new GenericApplicationContext();
|
|
XmlObjectDefinitionReader reader = new XmlObjectDefinitionReader(ctx);
|
|
reader.LoadObjectDefinitions("assembly://Spring.Core.Tests/Spring.Context.Support/contextB.xml");
|
|
reader.LoadObjectDefinitions("assembly://Spring.Core.Tests/Spring.Context.Support/contextC.xml");
|
|
reader.LoadObjectDefinitions("assembly://Spring.Core.Tests/Spring.Context.Support/contextA.xml");
|
|
ctx.Refresh();</programlisting>
|
|
|
|
<para>The implementation of IObjectDefinitionReader is responsible for
|
|
creating the configuration metadata, i.e., implementations of
|
|
RootObjectDefinition, etc. Note a web version of this application class
|
|
has not yet been implemented.</para>
|
|
|
|
<para>An example, with a<emphasis> yet to be created</emphasis> DLL
|
|
scanner, that would get configuration metadata from the .dll named
|
|
MyAssembly.dll located in the runtime path, would look something like
|
|
this</para>
|
|
|
|
<programlisting>GenericApplicationContext ctx = new GenericApplicationContext();
|
|
ObjectDefinitionScanner scanner = new ObjectDefinitionScanner(ctx);
|
|
scanner.scan("MyAssembly.dll");
|
|
ctx.refresh();</programlisting>
|
|
|
|
<para>Refer to the Spring API documentation for more information.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="objects-servicelocator">
|
|
<title>Service Locator access</title>
|
|
|
|
<para>The majority of the code inside an application is best written in a
|
|
Dependency Injection (Inversion of Control) style, where that code is
|
|
served out of an <classname>IObjectFactory</classname> or
|
|
<classname>IApplicationContext</classname> container, has its own
|
|
dependencies supplied by the container when it is created, and is
|
|
completely unaware of the container. However, there is sometimes a need
|
|
for singleton (or quasi-singleton) style access to an
|
|
<classname>IObjectFactory</classname> or
|
|
<classname>IApplicationContext</classname>. For example, third party code
|
|
may try to construct a new object directly without the ability to force it
|
|
to get these objects out of the IObjectFactory. Similarly, nested user
|
|
control components in a WinForms application are created inside the
|
|
generated code in InitializeComponent. If this user control would like to
|
|
obtain references to objects contained in the container it can use the
|
|
service locator style approach and 'reach out' from inside the code to
|
|
obtain the object it requires. (Note support for DI in WinForms is under
|
|
development.)</para>
|
|
|
|
<para>The <classname>Spring.Context.Support.ContextRegistry</classname>
|
|
class allows you to obtain a reference to an
|
|
<classname>IApplicationContext</classname> via a static locator method.
|
|
The <classname>ContextRegistry</classname> is initialized when creating an
|
|
<classname>IApplicationContext</classname> through use of the
|
|
<classname>ContextHandler</classname> discussed previously. The simple
|
|
static method <literal>GetContext()</literal> can then be used to retrieve
|
|
the context. Alternatively, if you create an
|
|
<classname>IApplicationContext</classname> though other means you can
|
|
register it with the <classname>ContextRegistry</classname> via the method
|
|
<literal>void RegisterContext(IApplicationContext context)</literal> in
|
|
the start-up code of your application. Hierarchical context retrieval is
|
|
also supported though the use of the <literal>GetContext(string
|
|
name)</literal> method, for example:<programlisting>IApplicationContex ctx = ContextRegistry.GetContext("mySubContext");</programlisting>
|
|
This would retrieve the nested context for the context configuration shown
|
|
previously.<programlisting><spring>
|
|
<context>
|
|
<resource uri="assembly://MyAssembly/MyProject/root-objects.xml"/>
|
|
<context name="mySubContext">
|
|
<resource uri="file://objects.xml"/>
|
|
</context>
|
|
</context>
|
|
</spring></programlisting></para>
|
|
|
|
<para>Do not call ContextRegistry.GetContext within a constructor as it
|
|
will result in and endless recursion. (This is scheduled to be fixed in
|
|
1.1.1) In this case it is quite likely you can use the
|
|
IApplicationContextAware interface and then retrieve other objects in a
|
|
service locator style inside an initialization method.</para>
|
|
|
|
<para>The <literal>ContextRegistry.Clear()</literal> method will remove
|
|
all contexts. On .NET 2.0, this will also call the ConfigurationManager's
|
|
RefreshSection method so that the Spring context configuration section
|
|
will be reread from disk when it is retrieved again. Note that in a web
|
|
application RefeshSection will not work as advertised and you will need to
|
|
touch the web.config files to reload a configuration.</para>
|
|
|
|
<para></para>
|
|
</sect1>
|
|
</chapter> |