6078 lines
290 KiB
XML
6078 lines
290 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!--
|
|
/*
|
|
* Copyright 2002-2008 the original author or authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
-->
|
|
<chapter version="5" xml:id="objects" xmlns="http://docbook.org/ns/docbook"
|
|
xmlns:ns6="http://www.w3.org/1999/xlink"
|
|
xmlns:ns5="http://www.w3.org/1998/Math/MathML"
|
|
xmlns:ns4="http://www.w3.org/1999/xhtml"
|
|
xmlns:ns3="http://www.w3.org/2000/svg"
|
|
xmlns:ns="http://docbook.org/ns/docbook">
|
|
<title>The IoC container</title>
|
|
|
|
<sect1 xml: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 <literal><link
|
|
ns6:href="http://www.springframework.net/doc/api/html/Spring.Objects.Factory.IObjectFactory.html">IObjectFactory</link></literal>
|
|
interface provides an advanced configuration mechanism capable of managing
|
|
objects of any nature. The <literal><link
|
|
ns6:href="http://www.springframework.net/doc/api/html/Spring.Context.IApplicationContext.html">IApplicationContext</link></literal>
|
|
interface builds on top of the <literal>IObjectFactory</literal> (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
|
|
<literal>WebApplicationContext</literal> for use in web
|
|
applications.</para>
|
|
|
|
<para>In short, the <literal>IObjectFactory</literal> provides the
|
|
configuration framework and basic functionality, while the
|
|
<literal>IApplicationContext</literal> adds more enterprise-centric
|
|
functionality to it. The <literal>IApplicationContext</literal> is a
|
|
complete superset of the <literal>IObjectFactory</literal>, and any
|
|
description of <literal>IObjectFactory</literal> 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 <literal>IObjectFactory</literal> and
|
|
<literal>IApplicationContext</literal>, with the <link
|
|
linkend="context-introduction">second part</link> covering those features
|
|
that apply only to the <literal>IApplicationContext</literal>
|
|
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 xml:id="objects-basics">
|
|
<title>Basics - containers and objects</title>
|
|
|
|
<sect2 xml:id="objects-factory">
|
|
<title>The container</title>
|
|
|
|
<para>The <literal>IObjectFactory</literal> 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
|
|
<literal>IObjectFactory</literal> interface that come supplied straight
|
|
out-of-the-box with Spring. The most commonly used
|
|
<literal>IObjectFactory</literal> implementation is the
|
|
<literal>XmlObjectFactory</literal> 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 <literal>XmlObjectFactory</literal> takes this XML configuration
|
|
metadata and uses it to create a fully configured system or application.
|
|
Interaction with the <literal>IObjectFactory</literal> interface is
|
|
discussed in <xref linkend="objects-factory-client" />. Additional
|
|
features offered by another implementation of
|
|
<literal>IObjectFactory</literal>, the
|
|
<literal>IApplicationContext</literal>, are discussed in section <xref
|
|
linkend="context-introduction" />.</para>
|
|
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata fileref="images/container-in-action.gif" format="GIF"></imagedata>
|
|
</imageobject>
|
|
</mediaobject>
|
|
|
|
<sect3 xml: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 xml:id="objects-factory-instantiation">
|
|
<title>Instantiating a container</title>
|
|
|
|
<para>Instantiating a Spring IoC container is straightforward.</para>
|
|
|
|
<programlisting language="csharp">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><link
|
|
ns6:href="http://www.springframework.net/doc/api/html/Spring.Core.IO.IResource.html">IResource</link></classname>
|
|
abstraction. The <literal>IResource</literal> interface provides a
|
|
simple and uniform interface to a wide array of IO resources that can
|
|
represent themselves as <literal>System.IO.Stream</literal>. 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 language="csharp">[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>.
|
|
The <literal>IResource</literal> abstraction is explained further in
|
|
<xref linkend="objects-iresource" />.</para>
|
|
|
|
<note>
|
|
<para>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.</para>
|
|
</note>
|
|
|
|
<para>The preferred way to create an
|
|
<literal>IApplicationContext</literal> or
|
|
<literal>IObjectFactory</literal> 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
|
|
<literal>IApplicationContext</literal> as the previous example is
|
|
<programlisting language="myxml"><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
|
|
<literal>Spring.Context.Support.XmlApplicationContext</literal> class,
|
|
so the following XML snippet is functionally equivalent to the first.
|
|
<programlisting language="myxml"><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
|
|
<literal>IApplicationContext</literal> using a custom configuration
|
|
section, one simply uses the following code; <programlisting
|
|
language="csharp">IApplicationContext ctx = ContextRegistry.GetContext();</programlisting>
|
|
The <literal>ContextRegistry</literal> 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
|
|
<literal>IConfigurationSectionHandler</literal> interface, namely the
|
|
<literal>Spring.Context.Support.ContextHandler</literal> class. The
|
|
handler class needs to be registered in the
|
|
<literal>configSections</literal> section of the .NET configuration file
|
|
as shown below. <programlisting language="myxml"><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
|
|
<literal>IObjectFactory</literal> interface, since Spring.NET code will
|
|
do it. For example, the ASP.NET web layer provides support code to load
|
|
a Spring.NET <literal>IApplicationContext</literal> 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
|
|
<literal>Spring.Context.Support.DefaultSectionHandler</literal> class as
|
|
the configuration section handler for inline object definitions. This
|
|
allows you to completely configure one or more
|
|
<literal>IApplicationContext</literal> instances within a single
|
|
standard .NET application configuration file as shown in the following
|
|
example. <programlisting language="myxml"><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="objects-factory-xml-import" />.</para>
|
|
|
|
<para>The <literal>IApplicationContext</literal> 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 xml:id="objects-factory-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 language="myxml"><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 xml: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-scopes" /></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 <literal>IObjectFactory</literal>
|
|
implementations also permit the registration of existing objects that
|
|
have been created outside the factory (by user code). The
|
|
<literal>DefaultListableObjectFactory</literal> class supports this
|
|
through the <literal>RegisterSingleton(..)</literal> method. (Typical
|
|
applications solely work with objects defined through metadata object
|
|
definitions though.)</para>
|
|
|
|
<sect3 xml:id="objects-objectname">
|
|
<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. 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 xml: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 xml: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 <literal>XmlObjectFactory</literal> implementation of the
|
|
<literal>IObjectFactory</literal> interface can consume object
|
|
definitions that have been defined in XML, for example...
|
|
<programlisting language="myxml"><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 <literal>Examples.ExampleObject</literal> 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
|
|
language="myxml"><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 xml: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 language="myxml"><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 xml: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
|
|
language="myxml"><!-- 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 xml: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 xml: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 language="csharp">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 language="myxml"><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 language="myxml"><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
|
|
language="myxml"><object id="myGenericObject"
|
|
type="GenericsPlay.ExampleGenericObject&lt;System.Collections.Generic.Dictionary&lt;int , string>>, GenericsPlay" /></programlisting>
|
|
It can be shortened to <programlisting language="myxml"><object id="myOtherGenericObject"
|
|
type="GenericsPlay.ExampleGenericObject&lt;GenericDictionary&lt;int , string>>, GenericsPlay" /></programlisting>
|
|
or even shorter <programlisting language="myxml"><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 xml: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 language="csharp">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
|
|
language="csharp">
|
|
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
|
|
language="myxml"><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 xml: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 language="myxml"><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 xml:id="objects-factory-client">
|
|
<title>Using the container</title>
|
|
|
|
<para>An <literal>IApplicationContext</literal> is essentially nothing
|
|
more than the interface for an advanced factory capable of maintaining a
|
|
registry of different objects and their dependencies. The
|
|
<literal>IApplicationContext</literal> 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 language="csharp">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 <literal>IApplicationContext</literal> is
|
|
simple. The <literal>IApplicationContext</literal> 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 xml: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 xml: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 xml: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 language="csharp">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 xml: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 language="csharp">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 language="myxml"><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 language="csharp">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 xml: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 language="myxml"><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 xml: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 language="myxml"><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 xml: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 language="myxml"><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 xml: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 language="csharp">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>
|
|
|
|
<para>Since you can mix both, Constructor- and Setter-based DI, it
|
|
is a good rule of thumb to use constructor arguments for mandatory
|
|
dependencies and setters for optional dependencies.</para>
|
|
</sidebar>
|
|
|
|
<para>The <literal>IObjectFactory</literal> 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
|
|
<literal>IObjectDefinition</literal> 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 <literal>IObjectFactory</literal> is created and
|
|
initialized with a configuration which describes all the
|
|
objects. Most Spring.NET users use an
|
|
<literal>IObjectFactory</literal> or
|
|
<literal>IApplicationContext</literal> variant that supports XML
|
|
format configuration files.</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>
|
|
</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>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>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 <literal>System.Type</literal> 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 <literal>TypeConverter</literal> 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
|
|
<literal>IApplicationContext</literal>), 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
|
|
<literal>ObjectCurrentlyInCreationException</literal>.</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 <literal>IApplicationContext</literal> 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
|
|
<literal>IApplicationContext</literal> 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 <literal>IIntializingObject</literal> callback method)
|
|
will all be invoked.</para>
|
|
</sect3>
|
|
|
|
<sect3 xml: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
|
|
language="myxml"><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 language="csharp">[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 language="myxml"><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 language="csharp">[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 <literal>ExampleObject</literal>.</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 language="myxml"><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 language="csharp">[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 language="myxml"><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 language="csharp">[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 xml: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 xml:id="objects-simple-values">
|
|
<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,
|
|
<literal>TypeConverter</literal> instances are used to convert these
|
|
string values from a <literal>System.String</literal> to the actual
|
|
property or argument type. Custom <literal>TypeConverter</literal>
|
|
implementations in the
|
|
<literal>Spring.Objects.TypeConverters</literal> namespace are used to
|
|
augment the functionality offered by the .NET BCL's default
|
|
<literal>TypeConverter</literal> implementations.</para>
|
|
|
|
<para>In the following example, we use a
|
|
<literal>SqlConnection</literal> 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 language="myxml"><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 language="myxml"><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 language="myxml"><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
|
|
language="myxml"><property name="targetName">
|
|
<idref local="theTargetObject"/>
|
|
</property></programlisting></para>
|
|
</sect4>
|
|
|
|
<sect4>
|
|
<title>Whitespace Handling</title>
|
|
|
|
<para>Usually all leading and trailing whitespaces are trimmed from
|
|
a <value /> element's text. In some cases it is necessary to
|
|
maintain whitespaces exactly as they are written into the xml
|
|
element. The parser does understand the xml:space attribute in this
|
|
case:</para>
|
|
|
|
<programlisting language="myxml"><property name="myProp">
|
|
<value xml:space="preserve"> &#x000a;&#x000d;&#x0009;</value>
|
|
</property></programlisting>
|
|
|
|
<para>The above configuration will result in the string " \n\r\t".
|
|
Note, that you don't have to explicitely specifiy the 'xml'
|
|
namespace on top of your configuration.</para>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3 xml: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
|
|
<literal>SqlConnection</literal> 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 <literal>IObjectFactory</literal> /
|
|
<literal>IApplicationContext</literal> (whether or not in the same XML
|
|
file), or parent <literal>IObjectFactory</literal> /
|
|
<literal>IApplicationContext</literal>. 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 language="myxml"><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 language="myxml"><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 <literal>IObjectFactory</literal>
|
|
(or<literal>IApplicationContext</literal>) of the current
|
|
<literal>IObjectFactory</literal> (or
|
|
<literal>IApplicationContext</literal>). 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 <literal>IObjectFactory</literal> or
|
|
<literal>IApplicationContext</literal> 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 language="myxml"><ref parent="someObject"/></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3 xml: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 language="myxml"><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 xml: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 language="myxml"><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 xml: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
|
|
<literal>IList<T></literal> and <literal>IDictionary<TKey,
|
|
TValue></literal>. The type parameter for these collections is
|
|
specified by using the XML attribute <literal>element-type</literal>
|
|
for <literal>IList<T></literal> and the XML attributes
|
|
<literal>key-type</literal> and <literal>value-type</literal> for
|
|
<literal>IDictionary<TKey, TValue></literal>. 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 <literal>IList<T></literal>
|
|
and <literal>IDictionary<TKey, TValue></literal> that is created
|
|
are <literal>System.Collections.Generic.List</literal> and
|
|
<literal>System.Collections.Generic.Dictionary</literal>.</para>
|
|
|
|
<para>The following class represents a lottery ticket and demonstrates
|
|
how to set the values of a generic IList. <programlisting
|
|
language="csharp">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 language="myxml"><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
|
|
<literal>Spring.Expressions.IExpression</literal> interface as the
|
|
generic type parameter for the IList element-type and the value-type
|
|
for IDictionary. <literal>Spring.Expressions.IExpression</literal> has
|
|
an associated type converter,
|
|
<literal>Spring.Objects.TypeConverters.ExpressionConverter</literal>
|
|
that is already pre-registered with Spring. <programlisting
|
|
language="csharp"> 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 language="myxml"><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 xml: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
|
|
<literal>string</literal> instances. The following configuration
|
|
demonstrates this behaviour...</para>
|
|
|
|
<programlisting language="myxml"><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 language="csharp">exampleObject.Email = "";</programlisting>
|
|
The special <literal><null/></literal> element may be used to
|
|
indicate a <literal>null</literal> value; to wit...</para>
|
|
|
|
<programlisting language="myxml"><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 language="csharp">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 language="csharp">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 language="myxml"><object id="person" type="Test.Objects.Person, Test.Objects">
|
|
<property name="[0]" value="Master Shake"/>
|
|
<property name="['one']" value="uno"/>
|
|
</object></programlisting></para>
|
|
|
|
<note>
|
|
<para>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>
|
|
|
|
<para>The older style configuration uses the following syntax
|
|
<programlisting language="myxml"><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 xml: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 language="myxml"><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
|
|
language="myxml"><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 language="myxml"><property name="myProperty">
|
|
<ref object="anotherObject"/>
|
|
</property>
|
|
|
|
<constructor-arg index="0">
|
|
<ref object="anotherObject"/>
|
|
</constructor-arg></programlisting> is equivalent to... <programlisting
|
|
language="myxml"><property name="myProperty" ref="anotherObject"/>
|
|
|
|
<constructor-arg index="0" ref="anotherObject"/></programlisting></para>
|
|
|
|
<note>
|
|
<para>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.</para>
|
|
</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
|
|
language="myxml"><entry>
|
|
<key>
|
|
<ref object="MyKeyObject"/>
|
|
</key>
|
|
<ref object="MyValueObject"/>
|
|
</entry></programlisting> Is equivalent to: <programlisting
|
|
language="myxml"><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 xml:id="objects-referencing-compound-properties">
|
|
<title>Compound property names and Spring expression
|
|
references</title>
|
|
|
|
<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 language="myxml"><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 language="myxml"><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>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Declarative Event Listener Registration</title>
|
|
|
|
<para>In C# events are built right into the language thanks to the
|
|
<literal>event</literal> keyword. Under the scenes, events are
|
|
essentially a shorthand notation for delegates with some additional
|
|
guidelines as to what the parameters to an event handler method should
|
|
be (i.e. a sender <literal>System.Object</literal> and an
|
|
<literal>System.EventArgs</literal> object).</para>
|
|
|
|
<para><programlisting language="csharp">public class EventSource
|
|
public event EventHandler Click;</programlisting></para>
|
|
|
|
<para>In use, .NET events are combined with one or more event handler
|
|
methods. Each handler method is programmatically added, or removed, from
|
|
the event and corresponds to an object's method that should be invoked
|
|
when a particular event occurs. When more than one handler method is
|
|
added to an event, then each of the registered methods will be invoked
|
|
in turn when an event occurs.</para>
|
|
|
|
<para><programlisting language="csharp">TestObject source = new TestObject();
|
|
TestEventHandler eventListener1 = new TestEventHandler();
|
|
TestEventHandler eventListener2 = new TestEventHandler();
|
|
|
|
source.Click += eventListener1.HandleEvent; // Adding the first event handler method to the event
|
|
source.Click += eventListener2.HandleEvent; // Adding a second event handler method to the event
|
|
|
|
source.OnClick(); // First eventListener1.HandleEvent is invoked, then eventListener2.HandleEvent</programlisting></para>
|
|
|
|
<para>When OnClick() is invoked, the event is fired.</para>
|
|
|
|
<para><programlisting language="csharp">public void OnClick()
|
|
{
|
|
if (Click != null)
|
|
{
|
|
Click(this, EventArgs.Empty); // Fire the event off to the registered handler methods
|
|
}
|
|
}</programlisting></para>
|
|
|
|
<para>One of the not so nice things about using events is that, without
|
|
employing late binding, you declare the objects that are registered with
|
|
a particular event programmatically. Spring .NET offers a way to
|
|
declaratively register your handler methods with particular events using
|
|
the <literal><listener></literal> element inside your
|
|
<literal><object></literal> elements.</para>
|
|
|
|
<sect3>
|
|
<title>Declarative event handlers</title>
|
|
|
|
<para>Rather than having to specifically declare in your code that you
|
|
are adding a method to be invoked on an event, using the
|
|
<literal><listener></literal> element you can register a plain
|
|
object's methods with the corresponding event declaratively in your
|
|
application configuration.</para>
|
|
|
|
<para>Using the <literal>listener</literal> element you can:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<link linkend="objects-simple-event-configuration">Configure a
|
|
method to be invoked when an event is fired.</link>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<link linkend="objects-handler-reg-ex-configuration">Register a
|
|
collection of handler methods based on a regular
|
|
expression.</link>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<link linkend="objects-event-name-reg-ex-configuration">Register
|
|
a handler method against an event name that contains a regular
|
|
expression.</link>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-simple-event-configuration">
|
|
<title>Configuring a method to be invoked when an event is
|
|
fired</title>
|
|
|
|
<para>The same event registration in the example above can be achieved
|
|
using configuration using the <literal><listener></literal>
|
|
element.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="eventListener1" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<!-- wired up to an event exposed on an instance -->
|
|
<listener event="Click" method="HandleEvent">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object>
|
|
|
|
<object id="eventListener2" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<!-- wired up to an event exposed on an instance -->
|
|
<listener event="Click" method="HandleEvent">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object></programlisting></para>
|
|
|
|
<para>In this case the two different objects will have their
|
|
<literal>HandleEvent</literal> method invoked, as indicated explicitly
|
|
using the <literal>method</literal> attribute, when a
|
|
<literal>Click</literal> event, as specified by the
|
|
<literal>event</literal> attribute, is triggered on the object
|
|
referred to by the <literal>ref</literal> element.</para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-handler-reg-ex-configuration">
|
|
<title>Registering a collection of handler methods based on a regular
|
|
expression</title>
|
|
|
|
<para>Regular expressions can be employed to wire up more than one
|
|
handler method to an object that contains one or more events.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<listener method="Handle.+">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object></programlisting></para>
|
|
|
|
<para>Here all the <literal>eventListener</literal>'s handler methods
|
|
that begin with 'Handle', and that have the corresponding two
|
|
parameters of a <literal>System.Object</literal> and a
|
|
<literal>System.EventArgs</literal>, will be registered against all
|
|
events exposed by the <literal>source</literal> object.</para>
|
|
|
|
<para>You can also use the name of the event in regular expression to
|
|
filter your handler methods based on the type of event
|
|
triggered.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<!-- For the Click event, the HandleClick handler method will be invoked. -->
|
|
<listener method="Handle${event}">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-event-name-reg-ex-configuration">
|
|
<title>Registering a handler method against an event name that
|
|
contains a regular expression</title>
|
|
|
|
<para>Finally, you can register an object's handler methods against a
|
|
selection of events, filtering based on their name using a regular
|
|
expression.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<listener method="HandleEvent" event="Cl.+">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object></programlisting></para>
|
|
|
|
<para>In this example the <literal>eventListener</literal>'s
|
|
<literal>HandleEvent</literal> handler method will be invoked for any
|
|
event that begins with 'Cl'.</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml: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
|
|
language="myxml"><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 language="myxml"><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>
|
|
|
|
<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>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Lazily-instantiated objects</title>
|
|
|
|
<para>The default behavior for <literal>IApplicationContext</literal>
|
|
implementations is to eagerly pre-instantiate all singleton objects at
|
|
startup. Pre-instantiation means that an
|
|
<literal>IApplicationContext</literal> 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 <literal>IApplicationContext</literal>, 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 language="myxml"><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
|
|
<literal>IApplicationContext</literal>, the object named
|
|
<literal>'lazy'</literal> will not be eagerly pre-instantiated when the
|
|
<literal>IApplicationContext</literal> 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
|
|
<literal>IApplicationContext</literal> 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 language="myxml"><objects default-lazy-init="true">
|
|
<!-- no objects will be pre-instantiated... -->
|
|
</objects></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml: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 <literal>IObjectDefinition</literal> with a collaborator
|
|
typed <literal>SqlConnection</literal>, Spring.NET will search
|
|
the entire object factory for an object definition of type
|
|
<literal>SqlConnection</literal> 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 xml: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 xml: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
|
|
linkend="objects-factory-aware-objectfactoryaware">made aware of the
|
|
container</link> by implementing the
|
|
<literal>IObjectFactoryAware</literal> 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 language="csharp">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 xml: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 <link
|
|
ns6:href="http://blog.springframework.com/rod/?p=1">this blog
|
|
entry</link>.</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
|
|
<literal>CommandManager</literal> class is not going to have any
|
|
Spring dependencies, as can be seen in this reworked example
|
|
below:</para>
|
|
|
|
<programlisting language="csharp">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 language="myxml"><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 language="myxml"><!-- 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 xml: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 <literal>XmlObjectFactory</literal>, 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 language="csharp">public class MyValueCalculator {
|
|
|
|
public virtual string ComputeValue(string input) {
|
|
// ... some real code
|
|
}
|
|
|
|
// ... some other methods
|
|
}</programlisting>
|
|
|
|
<para>A class implementing the
|
|
<literal>Spring.Objects.Factory.Support.IMethodReplacer</literal>
|
|
interface is needed to provide the new (injected) method
|
|
definition.</para>
|
|
|
|
<programlisting language="csharp">/// <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 language="myxml"><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
|
|
<literal>System.String</literal>.</para>
|
|
|
|
<programlisting language="csharp"> 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 xml: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
|
|
<literal>MethodInvokingFactoryObject</literal> 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,
|
|
<literal>PropertyRetrievingFactoryObject</literal> and
|
|
<literal>FieldRetrievingFactoryObject</literal> allow you to retrieve
|
|
values from another object's property or field value. These classes
|
|
implement the <literal>IFactoryObject</literal> 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 <literal>PropertyRetrievingFactoryObject</literal> is an
|
|
<literal>IFactoryObject</literal> 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 <literal>PropertyRetrievingFactoryObject</literal> 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 <literal>System.Type</literal>) 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 <literal>IFactoryObject</literal> 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
|
|
language="myxml"><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
|
|
<literal>PropertyRetrievingFactoryObject</literal> to evaluate a
|
|
<literal>static</literal> property is shown below.</para>
|
|
|
|
<programlisting language="myxml"><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 language="myxml"><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 <literal>FieldRetrievingFactoryObject</literal> class
|
|
addresses much the same area of concern as the
|
|
<literal>PropertyRetrievingFactoryObject</literal> described in the
|
|
previous section. However, as its name might suggest, the
|
|
<literal>FieldRetrievingFactoryObject</literal> 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
|
|
<literal>FieldRetrievingFactoryObject</literal> to look up the value
|
|
of a (public, static) field exposed on a class</para>
|
|
|
|
<para><programlisting language="myxml"><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 language="myxml"><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 xml:id="objects-methodfactory">
|
|
<title>Setting a property or constructor argument to the return value
|
|
of a method invocation.</title>
|
|
|
|
<para>The <literal>MethodInvokingFactoryObject</literal> 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 <literal>PropertyRetrievingFactoryObject</literal> and
|
|
<literal>FieldRetrievingFactoryObject</literal> classes dealt with
|
|
simply looking up and returning the value of property or field on an
|
|
object or class, the <literal>MethodInvokingFactoryObject</literal>
|
|
allows one to set a constructor or property to the return value of an
|
|
arbitrary method invocation,</para>
|
|
|
|
<para>The <literal>MethodInvokingFactoryObject</literal> 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 <literal>MethodInvokingFactoryObject</literal> 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
|
|
<literal>IObjectFactory</literal> definition) uses the
|
|
<literal>MethodInvokingFactoryObject</literal> class to force a call
|
|
to a static factory method prior to the instantiation of the
|
|
object...</para>
|
|
|
|
<para><programlisting language="myxml"><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 <literal>MethodInvokingFactoryObject</literal> 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 <literal>MethodInvokingFactoryObject</literal> object
|
|
have been set, and if the
|
|
<literal>MethodInvokingFactoryObject</literal> 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
|
|
<literal>Type</literal> 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 <literal>Type</literal>. This is shown in the example below
|
|
<programlisting language="myxml"><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 (<literal>String</literal>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
|
|
language="myxml"><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
|
|
<literal>MethodInvokingFactoryObject</literal> to call an instance
|
|
method.<programlisting language="myxml"><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
|
|
<literal>MethodInvokingFactoryObject</literal> 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 <literal>params</literal> keyword (in C#),
|
|
and its attendant (XML) configuration... <programlisting
|
|
language="csharp">[C#]
|
|
public class MyClassFactory
|
|
{
|
|
public object CreateObject(Type objectType, params string[] arguments)
|
|
{
|
|
return ... // implementation elided for clarity...
|
|
}
|
|
}</programlisting> <programlisting language="myxml"><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 xml:id="objects-objectfactories">
|
|
<title>Provided IFactoryObject implementations</title>
|
|
|
|
<para>In addition to <literal>PropertyRetrievingFactoryObject</literal>,
|
|
<literal>MethodInvokingFactoryObject</literal>, and
|
|
<literal>FieldRetrievingFactoryObject </literal> Spring.NET comes with
|
|
other useful implementations of the <literal>IFactoryObject</literal>
|
|
interface. These are discussed below.</para>
|
|
|
|
<sect3 xml:id="objects-objectfactories-log4net">
|
|
<title>Common logging</title>
|
|
|
|
<para>The <literal>LogFactoryObject</literal> 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 <link
|
|
ns6:href="http://netcommon.sourceforge.net/">here</link>. 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
|
|
language="myxml"><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 xml:id="objects-factory-scopes">
|
|
<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 xml: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 language="myxml"><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 xml: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 language="myxml"><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 xml: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 xml: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 <literal>TypeConverter</literal> 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 <literal>TypeConverter</literal> 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 <literal>Font</literal> is shown below. <programlisting
|
|
language="csharp">[Serializable, TypeConverter(typeof(FontConverter)), ...]
|
|
public sealed class Font : MarshalByRefObject, ICloneable, ISerializable, IDisposable
|
|
{
|
|
// Methods
|
|
|
|
... etc ..
|
|
}</programlisting></para>
|
|
|
|
<sect2 xml:id="objects-type-conversion-enums">
|
|
<title>Type Conversion for Enumerations</title>
|
|
|
|
<para>The default type converter for enumerations is the
|
|
<literal>System.ComponentModel.EnumConverter</literal> class. To specify
|
|
the value for an enumerated property, simply use the name of the
|
|
property. For example the <literal>TestObject</literal> class has a
|
|
property of the enumerated type <literal>FileMode</literal>. One of the
|
|
values for this enumeration is named <literal>Create</literal>. The
|
|
following XML fragment shows how to configure this property</para>
|
|
|
|
<programlisting language="myxml"><object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="name" value="Rod"/>
|
|
<property name="FileMode" value="Create"/>
|
|
</object></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-type-conversion-builtin">
|
|
<title>Built-in TypeConverters</title>
|
|
|
|
<para>Spring.NET pre-registers a number of custom
|
|
<literal>TypeConverter</literal> instances (for example, to convert a
|
|
type expressed as a string into a real <literal>System.Type</literal>
|
|
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 <literal>TypeConverters</literal></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
|
|
<literal>System.Types</literal> to actual
|
|
<literal>System.Types</literal> and the other way
|
|
around.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>FileInfoConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving strings to a
|
|
<literal>System.IO.FileInfo</literal> 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
|
|
<literal>System.Resources.ResourceManager</literal>
|
|
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
|
|
<literal>System.Drawing.Color</literal> structure.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>ExpressionConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string into an instance of an
|
|
object that implements the <literal>IExpression</literal>
|
|
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
|
|
<literal>System.Types</literal>, 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 xml: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
|
|
<literal>TypeConverterRegistry</literal> class. The <emphasis>most
|
|
convenient way</emphasis> if using an XML based implementation of
|
|
<literal>IObjectFactory</literal> or
|
|
<literal>IApplicationContext</literal> is to use the custom
|
|
configuration section handler
|
|
<literal>TypeConverterSectionHandler</literal> 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
|
|
<literal>Spring.Objects.Factory.Config.CustomConverterConfigurer</literal>.
|
|
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 xml: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 <literal>TypeConverter</literal>
|
|
attribute. The type converter class is standalone and inherits from
|
|
the <literal>TypeConverter</literal> 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 language="csharp">public class ExoticType
|
|
{
|
|
private string name;
|
|
|
|
public ExoticType(string name)
|
|
{
|
|
this.name = name;
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get { return this.name; }
|
|
}
|
|
}</programlisting> and <programlisting language="csharp">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 language="myxml"><object name="sample" type="SimpleApp.DependsOnExoticType, SimpleApp">
|
|
<property name="exoticType" value="aNameForExoticType"/>
|
|
</object></programlisting> The TypeConverter looks like this:
|
|
<programlisting language="csharp">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
|
|
<literal>CustomConverterConfigurer</literal> to register the new
|
|
<literal>TypeConverter</literal> with the
|
|
<literal>IApplicationContext</literal>, which will then be able to use
|
|
it as needed: <programlisting language="myxml"><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 xml:id="objects-factory-nature">
|
|
<title>Customizing the nature of an object</title>
|
|
|
|
<sect2 xml: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
|
|
<literal>IObjectPostProcessor</literal> 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
|
|
<literal>IObjectPostProcessor</literal> 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 xml:id="objects-factory-lifecycle-initializingobject">
|
|
<title>IInitializingObject / <literal>init-method</literal></title>
|
|
|
|
<para>The
|
|
<literal>Spring.Objects.Factory.IInitializingObject</literal>
|
|
interface gives you the ability to perform initialization work after
|
|
all the necessary properties on an object are set by the container.
|
|
The <literal>IInitializingObject</literal> 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>
|
|
<literal>Exception</literal> to indicate misconfiguration,
|
|
initialization failures, etc.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<note>
|
|
<para>Generally, the use of the
|
|
<literal>IInitializingObject</literal> 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).</para>
|
|
</note>
|
|
|
|
<para><programlisting language="myxml"><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 language="myxml"><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>
|
|
<para>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.</para>
|
|
</note>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-factory-lifecycle-disposableobject">
|
|
<title>IDisposable / <literal>destroy-method</literal></title>
|
|
|
|
<para>The <literal>System.IDisposable</literal> interface provides you
|
|
with the ability to get a callback when an
|
|
<literal>IObjectFactory</literal> is destroyed. The
|
|
<literal>IDisposable</literal> 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>
|
|
<literal>Exception</literal> here... however, any such
|
|
<literal>Exception</literal> will not stop the destruction of
|
|
the container - it will only get logged.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<note>
|
|
<para><emphasis>Note: If you choose you can avoid having your class
|
|
implement <literal>IDisposable</literal> 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></para>
|
|
</note>
|
|
|
|
<para><programlisting language="myxml"><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 language="myxml"><object id="exampleInitObject" type="Examples.AnotherExampleObject"/>
|
|
[C#]
|
|
public class AnotherExampleObject : IDisposable
|
|
{
|
|
public void Dispose()
|
|
{
|
|
// do some destruction work
|
|
}
|
|
}</programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-factory-aware">
|
|
<title>Knowing who you are</title>
|
|
|
|
<sect3 xml:id="objects-factory-aware-objectfactoryaware">
|
|
<title>IObjectFactoryAware</title>
|
|
|
|
<para>A class which implements the
|
|
<literal>Spring.Objects.Factory.IObjectFactoryAware</literal>
|
|
interface is provided with a reference to the
|
|
<literal>IObjectFactory</literal> 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
|
|
<literal>IObjectFactory</literal> that created them Programatically,
|
|
through the <literal>IObjectFactory</literal> 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 xml:id="objects-factory-aware-objectnameaware">
|
|
<title>IObjectNameAware</title>
|
|
|
|
<para>The <literal>Spring.Objects.Factory.IObjectNameAware</literal>
|
|
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 xml: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 <literal>IObjectFactory</literal>
|
|
Programatically, child object definitions are represented by the
|
|
<literal>ChildObjectDefinition</literal> class. Most users will never work
|
|
with them on this level, instead configuring object definitions
|
|
declaratively in something like the <literal>XmlObjectFactory</literal>.
|
|
In an <literal>XmlObjectFactory</literal> 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 language="myxml"><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 language="myxml"><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>
|
|
<para>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.</para>
|
|
</note>
|
|
</sect1>
|
|
|
|
<sect1 xml: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 <literal>IObjectFactory</literal> enables you to read
|
|
object definitions and access them using the object factory. When using
|
|
just the <literal>IObjectFactory</literal> you would create an instance of
|
|
one and then read in some object definitions in the XML format as follows:
|
|
<programlisting language="csharp">[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
|
|
language="csharp">[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 language="myxml"><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/>
|
|
<object id="anotherObject" type="Examples.ExampleObject, ExamplesLibrary" singleton="false"/></programlisting>
|
|
<programlisting language="csharp">[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 <literal>IObjectFactory</literal> is
|
|
surprisingly simple. The <literal>IObjectFactory</literal> 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 <literal>IObjectFactory</literal> 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
|
|
<literal>IObjectFactory</literal> 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 <literal>IObjectFactory</literal> 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 <literal>Type</literal>. 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
|
|
<literal>IObjectDefinition</literal>.</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 <literal>IObjectFactory</literal>,
|
|
<literal>IConfigurableObjectFactory</literal> 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
|
|
<literal>IObjectFactory</literal> class hierarchy.</para>
|
|
|
|
<sect2>
|
|
<title>Obtaining an <literal>IFactoryObject</literal>, not its
|
|
product</title>
|
|
|
|
<para>Sometimes there is a need to ask an
|
|
<literal>IObjectFactory</literal> for an actual
|
|
<literal>IFactoryObject</literal> 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
|
|
<literal>IObjectFactory</literal> and
|
|
<literal>IApplicationContext</literal> interfaces. So for a given
|
|
<literal>IFactoryObject</literal> with an id
|
|
<literal>myObject</literal>, invoking
|
|
<literal>GetObject("myObject")</literal> on the
|
|
<literal>IObjectFactory</literal> will return the product of the
|
|
<literal>IFactoryObject</literal>, but invoking
|
|
<literal>GetObject("&myObject")</literal> will return the
|
|
<literal>IFactoryObject</literal> 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 <literal>IObjectFactory</literal> or
|
|
<literal>IApplicationContext</literal> 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 xml:id="objects-factory-customizing">
|
|
<title>Customizing objects with
|
|
<literal>IObjectPostProcessors</literal></title>
|
|
|
|
<para>The first extension point that we will look at is the
|
|
<literal>Spring.Objects.Factory.Config.IObjectPostProcessor</literal>
|
|
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
|
|
<literal>IObjectPostProcessor</literal> implementations.</para>
|
|
|
|
<para>You can configure multiple
|
|
<literal>IObjectPostProcessors</literal> if you wish. You can control
|
|
the order in which these <literal>IObjectPostProcessor</literal> execute
|
|
by setting the 'Order' property (you can only set this property if the
|
|
<literal>IObjectPostProcessor</literal> implements the
|
|
<literal>IOrdered</literal> interface; if you write your own
|
|
<literal>IObjectPostProcessor</literal> you should consider implementing
|
|
the <literal>IOrdered</literal> interface too); consult the SDK docs for
|
|
the <literal>IObjectPostProcessor</literal> and
|
|
<literal>IOrdered</literal> interfaces for more details.</para>
|
|
|
|
<note>
|
|
<para><literal>IObjectPostProcessor</literal> operate on object
|
|
instances; that is to say, the Spring IoC container will have
|
|
instantiated a object instance for you, and then
|
|
<literal>IObjectPostProcessors</literal> 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
|
|
<literal>IObjectFactoryPostProcessor</literal> (described below in the
|
|
section entitled <link
|
|
linkend="objects-factory-customizing-factory-postprocessors">Customizing
|
|
configuration metadata with
|
|
IObjectFactoryPostProcessors.</link></para>
|
|
|
|
<para>Also, <literal>IObjectPostProcessors</literal> are scoped
|
|
per-container. This is only relevant if you are using container
|
|
hierarchies. If you define a <literal>IObjectPostProcessor</literal>
|
|
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 <literal>IObjectPostProcessors</literal> in another
|
|
container, even if both containers are part of the same
|
|
hierarchy.</para>
|
|
</note>
|
|
|
|
<para>The
|
|
<literal>Spring.Objects.Factory.Config.IObjectPostProcessor</literal>
|
|
interface, which consists of two callback methods shown below.
|
|
<programlisting language="csharp">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
|
|
<literal>IInitializingObject</literal> 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 <literal>IInstantiationAwareObjectPostProcessor</literal>
|
|
and <literal>IDestructionAwareObjectPostProcessor</literal> defined
|
|
below <programlisting language="csharp">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 <literal>PostProcessBeforeInstantiation</literal>
|
|
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
|
|
<literal>PostProcessAfterInstantiation</literal> 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
|
|
<literal>PostProcessPropertyValues</literal> 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 <literal>[Required]</literal> attribute or to perform
|
|
attribute based wiring, i.e. adding the attribute
|
|
<literal>[Inject("objectName")]</literal> on a property. Both of these
|
|
features are scheduled to be included in Spring .12.</para>
|
|
|
|
<para>The <literal>IDestructionAwareObjectPostProcessor</literal>
|
|
callback contains a single method,
|
|
<literal>PostProcessBeforeDestruction</literal>, which is called before
|
|
a singleton's destroy method is invoked.</para>
|
|
|
|
<para>It is important to know that the <literal>IObjectFactory</literal>
|
|
treats object post-processors slightly differently than the
|
|
<literal>IApplicationContext</literal>. An
|
|
<literal>IApplicationContext</literal> will automatically detect any
|
|
objects which are deployed into it that implement the
|
|
<literal>IObjectPostProcessor</literal> 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 language="csharp">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 <literal>IApplicationContext</literal>
|
|
implementations are preferred above plain
|
|
<literal>IObjectFactory</literal> 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
|
|
<literal>IObjectPostProcessor</literal> interface are special, and so
|
|
they are treated differently by the container. All
|
|
<literal>IObjectPostProcessors</literal> and their directly referenced
|
|
object will be instantiated on startup, as part of the special startup
|
|
phase of the IApplicationContext, then all those
|
|
<literal>IObjectPostProcessors</literal> will be registered in a
|
|
sorted fashion - and applied to all further objects. Since AOP
|
|
auto-proxying is implemented as a
|
|
<literal>IObjectPostProcessor</literal> itself, no
|
|
<literal>IObjectPostProcessors</literal> 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
|
|
<literal>IObjectPostProcessors</literal> (for example: not eligible
|
|
for auto-proxying)”.</para>
|
|
</note>
|
|
|
|
<para></para>
|
|
|
|
<sect3 xml: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 language="csharp">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 language="myxml"><?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 -->
|
|
<object type="Spring.IocQuickStart.MovieFinder.TracingObjectPostProcessor, Spring.IocQuickStart.MovieFinder"/>
|
|
</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 language="csharp">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 xml: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
|
|
<literal>ObjectInitializationException</literal> 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 language="csharp">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
|
|
<literal>MovieLister</literal> 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 language="myxml"><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
|
|
<literal>RequiredAttributeObjectPostProcessor</literal> 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 language="myxml"><object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"/></programlisting>
|
|
|
|
<para>Finally, one can configure an instance of the
|
|
<literal>RequiredAttributeObjectPostProcessor</literal> 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
|
|
<literal>RequiredAttributeObjectPostProcessor</literal> 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 <literal>RequiredAttributeObjectPostProcessor</literal>
|
|
instance <literal>[Mandatory]</literal>-aware like so:</para>
|
|
|
|
<programlisting language="myxml"><object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core">
|
|
<property name="RequiredAttributeType" value="MyApp.Attributes.MandatoryAttribute, MyApp"/>
|
|
</object></programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml: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
|
|
<literal>Spring.Objects.Factory.Config.IObjectFactoryPostProcessor</literal>.
|
|
The semantics of this interface are similar to the
|
|
<literal>IObjectPostProcessor</literal>, with one major difference.
|
|
<literal>IObjectFactoryPostProcessors</literal> operate on; that is to
|
|
say, the Spring IoC container will allow
|
|
<literal>IObjectFactoryPostProcessors</literal> 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 language="csharp">public interface IObjectFactoryPostProcessor
|
|
{
|
|
void PostProcessObjectFactory (IConfigurableListableObjectFactory factory);
|
|
}
|
|
</programlisting></para>
|
|
|
|
<para>You can configure multiple
|
|
<literal>IObjectFactoryPostProcessors</literal> if you wish. You can
|
|
control the order in which these
|
|
<literal>IObjectFactoryPostProcessors</literal> execute by setting the
|
|
'Order' property (you can only set this property if the
|
|
<literal>IObjectFactoryPostProcessors</literal> implements the
|
|
<literal>IOrdered</literal> interface; if you write your own
|
|
<literal>IObjectFactoryPostProcessors</literal> you should consider
|
|
implementing the <literal>IOrdered</literal> interface too); consult the
|
|
SDK docs for the <literal>IObjectFactoryPostProcessors</literal> and
|
|
<literal>IOrdered</literal> 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 <literal>IObjectObjectPostProcessor</literal> (described
|
|
above in the section entitled <link
|
|
linkend="objects-factory-customizing">Customizing objects with
|
|
<literal>IObjectPostProcessors</literal></link>.</para>
|
|
|
|
<para>Also, <literal>IObjectFactoryPostProcessors</literal> are scoped
|
|
per-container. This is only relevant if you are using container
|
|
hierarchies. If you define a
|
|
<literal>IObjectFactoryPostProcessors</literal> 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
|
|
<literal>IObjectFactoryPostProcessors</literal> 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 <literal>IObjectFactory</literal>, the process of applying
|
|
an <literal>IObjectFactoryPostProcessor</literal> is manual, and will be
|
|
similar to this:</para>
|
|
|
|
<para><programlisting language="csharp">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
|
|
xml:id="objects-factory-autodetect-objectfactorypostprocessors" />This
|
|
explicit registration step is not convenient, and this is one of the
|
|
reasons why the various <literal>IApplicationContext</literal>
|
|
implementations are preferred above plain
|
|
<literal>IObjectFactory</literal> implementations in the vast majority
|
|
of Spring-backed applications, especially when using
|
|
<literal>IObjectFactoryPostProcessors</literal>.</para>
|
|
|
|
<para>An <literal>IApplicationContext</literal> 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 <literal>IObjectPostProcessors</literal>,
|
|
you typically don't want to have
|
|
<literal>IObjectFactoryPostProcessors</literal> 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
|
|
<literal>IObjectFactoryPostProcessor</literal> object definitions with
|
|
'lazy-init="false"'.</para>
|
|
</note>
|
|
|
|
<sect3 xml:id="objects-factory-placeholderconfigurer">
|
|
<title>Example: The
|
|
<literal>PropertyPlaceholderConfigurer</literal></title>
|
|
|
|
<para>The <literal>PropertyPlaceholderConfigurer</literal> 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 <literal>IObjectFactoryPostProcessor</literal>
|
|
interface. This means that as described here, applying a
|
|
<literal>PropertyPlaceholderConfigurer</literal> is much more
|
|
convenient when using an <literal>IApplicationContext</literal>. For
|
|
this reason, it is recommended that users wishing to use this or other
|
|
object factory postprocessors use an
|
|
<literal>IApplicationContext</literal> instead of an
|
|
<literal>IObjectFactory</literal>.</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
|
|
language="myxml"><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 language="myxml"><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="${maxResults}"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
</object>
|
|
|
|
<object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data">
|
|
<property name="connectionstring" value="${connection.string}"/>
|
|
</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
|
|
<literal>PropertyPlaceholderConfigurer</literal> 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 <literal>PropertyPlaceholderConfigurer</literal> class also
|
|
supports retrieving name value pairs from other
|
|
<literal>IResource</literal> locations. These can be specified using
|
|
the <literal>Location</literal> and <literal>Locations</literal>
|
|
properties of the <literal>PropertyPlaceHolderConfigurer</literal>
|
|
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>
|
|
<para>In an ASP.NET environment you must specify the full, four-part
|
|
name of the assembly when using a
|
|
<literal>NameValueFileSectionHandler</literal> <programlisting
|
|
language="myxml">
|
|
<section name="hibernateConfiguration"
|
|
type="System.Configuration.NameValueFileSectionHandler, System,
|
|
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
|
</programlisting></para>
|
|
</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 language="myxml"><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 language="myxml"><object id="TestObject" type="Simple.TestObject, MyAssembly">
|
|
<property name="age" expression="${ageExpression}"/>
|
|
<property name="spouse" ref="${spouse-ref}"/>
|
|
</object></programlisting>
|
|
</sect4>
|
|
|
|
<sect4 xml: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 <literal>EnvironmentVariablesMode</literal>
|
|
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
|
|
<literal>PropertyPlaceholderConfigurer</literal> XML is modified to
|
|
enable override usage is shown below <programlisting
|
|
language="myxml"><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 xml:id="objects-factory-overrideconfigurer">
|
|
<title>Example: The
|
|
<literal>PropertyOverrideConfigurer</literal></title>
|
|
|
|
<para>The <literal>PropertyOverrideConfigurer</literal>, another
|
|
object factory post-processor, is similar to the
|
|
<literal>PropertyPlaceholderConfigurer</literal>, 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
|
|
<literal>PropertyOverrideConfigurer</literal> 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
|
|
<literal>PropertyPlaceHolderConfigurer</literal> 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 language="myxml"><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 language="myxml"><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 xml: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><literal>ConfigSectionVariableSource</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>PropertyFileVariableSource</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>EnvironmentVariableSource</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>CommandLineArgsVariableSource</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>RegistryVariableSource</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>SpecialFolderVariableSource</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>ConnectionStringsVariableSource</literal></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>You use this by defining an instance of
|
|
<literal>Spring.Objects.Factory.Config.VariablePlaceholderConfigurer</literal>
|
|
in your configuration and set the property
|
|
<literal>VariableSource</literal> to a single
|
|
<literal>IVariableSource</literal> instance or the list property
|
|
<literal>VariableSources</literal> to a list of
|
|
<literal>IVariableSource</literal> instances. In the case of the same
|
|
property defined in multiple <literal>IVariableSource</literal>
|
|
implementations, the first one in the list that contains the property
|
|
value will be used. <programlisting language="myxml"><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 language="csharp">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 xml:id="objects-factory-lifecycle-factoryobject">
|
|
<title>Customizing instantiation logic using
|
|
<literal>IFactoryObjects</literal></title>
|
|
|
|
<para>The <literal>Spring.Objects.Factory.IFactoryObject</literal>
|
|
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 <literal>IFactoryObject</literal> 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><literal>IFactoryObject</literal></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
|
|
<literal>PropertyRetrievingFactoryObject</literal> and
|
|
<literal>FieldRetrievingFactoryObject</literal>. 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 <link
|
|
ns6:href="http://jira.springframework.org/browse/SPRNET-133#action_19743">here</link>.</para>
|
|
|
|
<para>Finally, there is sometimes a need to ask a container for an
|
|
actual <literal>IFactoryObject</literal> 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
|
|
<literal>IObjectFactory</literal> (including
|
|
<literal>IApplicationContext</literal>). So for a given
|
|
<literal>IFactoryObject</literal> with an id of
|
|
'<literal>myObject</literal>', invoking
|
|
<literal>GetObject("myObject")</literal> on the container will return
|
|
the product of the <literal>IFactoryObject</literal>, but invoking
|
|
<literal>GetObject("&myObject")</literal> will return the
|
|
<literal>IFactoryObject</literal> instance itself.</para>
|
|
|
|
<sect3>
|
|
<title>IConfigurableFactoryObject</title>
|
|
|
|
<para>The
|
|
<literal>Spring.Objects.Factory.IConfigurableFactoryObject</literal>
|
|
interface inherits from <literal>IFactoryObject</literal> 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><literal>IConfigurableFactoryObject</literal> implementions you
|
|
already have examples of in <xref linkend="client-side" /> are
|
|
<literal>WebServiceProxyFactory</literal>.</para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="context-introduction">
|
|
<title>The <literal>IApplicationContext</literal></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 <literal>IApplicationContext</literal> interface, which
|
|
enhances the functionality provided by the
|
|
<literal>IObjectFactory</literal> 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 <literal>IApplicationContext</literal>
|
|
Programatically).</para>
|
|
|
|
<para>The basis for the context module is the
|
|
<literal>IApplicationContext</literal> interface, located in the
|
|
<literal>Spring.Context</literal> namespace. Deriving from the
|
|
<literal>IObjectFactory</literal> interface, it provides all the
|
|
functionality of the <literal>IObjectFactory</literal>. 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
|
|
<literal>IMessageSource</literal>.</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
|
|
<literal>IResourceLoader</literal></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><literal>IApplicationContext</literal></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 <literal>IApplicationContext</literal> includes all the
|
|
functionality the object factory via its inheritance of the
|
|
<literal>IObjectFactory</literal> interface, it is generally recommended
|
|
to be used over the <literal>IObjectFactory</literal> 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 <literal>IObjectFactory</literal> 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 <literal>IApplicationContext</literal> is what you will
|
|
want to use. Spring generally makes heavy use of the
|
|
<literal>IObjectPostProcessor</literal> extension point (to effect
|
|
proxying and suchlike), and if you are using just a plain
|
|
<literal>IObjectFactory</literal> 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 <literal>IObjectFactory</literal> and
|
|
<literal>IApplicationContext</literal> interfaces (and attendant
|
|
implementations). The following sections describe functionality that
|
|
<literal>IApplicationContext</literal> adds to the basic
|
|
<literal>IObjectFactory</literal> capabilities in a lot more depth than
|
|
the said feature matrix.)</para>
|
|
|
|
<anchor xml:id="context-introduction-ctx-vs-objectfactory-feature-matrix" />
|
|
|
|
<table pgwide="1">
|
|
<title>Feature Matrix</title>
|
|
|
|
<tgroup cols="3">
|
|
<colspec align="left" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry align="center">Feature</entry>
|
|
|
|
<entry align="center"><literal>IObjectFactory</literal></entry>
|
|
|
|
<entry
|
|
align="center"><literal>IApplicationContext</literal></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 <literal>IObjectPostProcessor</literal>
|
|
registration</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Automatic
|
|
<literal>IObjectFactoryPostProcessor</literal>
|
|
registration</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Convenient <literal>IMessageSource</literal>
|
|
access</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para><literal>ApplicationEvent</literal>
|
|
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 xml: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 language="myxml"><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.<literal>ResourceHandlersSectionHandler</literal>, 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
|
|
<literal>IObjectFactory</literal> and
|
|
<literal>IApplicationContext</literal> 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 xml: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
|
|
<literal>ObjectsNamespaceParser</literal> 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>
|
|
|
|
<note>
|
|
<para>As of Spring.NET 1.2.0 it is no longer necessary to explicitly
|
|
configure the namespace parsers that come with Spring via a custom
|
|
section in App.config. You will still need to register custom
|
|
namespace parsers if you are writing your own.</para>
|
|
</note>
|
|
|
|
<programlisting language="myxml"><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>
|
|
|
|
<para>You can also register custom parser programmatically using the
|
|
NamespaceParserRegistry. Here is an example taken from the code used in
|
|
the Transactions Quickstart application.</para>
|
|
|
|
<programlisting language="csharp">NamespaceParserRegistry.RegisterParser(typeof(DatabaseNamespaceParser));
|
|
NamespaceParserRegistry.RegisterParser(typeof(TxNamespaceParser));
|
|
NamespaceParserRegistry.RegisterParser(typeof(AopNamespaceParser));
|
|
|
|
IApplicationContext context =
|
|
new XmlApplicationContext("assembly://Spring.TxQuickStart.Tests/Spring.TxQuickStart/system-test-local-config.xml");</programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-custom-resourcehandler">
|
|
<title>Registering custom resource handlers</title>
|
|
|
|
<para>Creating a custom resource handler means implementing the
|
|
<literal>IResource</literal> interface. The base class
|
|
<literal>AbstractResource</literal> is a useful starting point. Look at
|
|
the Spring source for classes such as
|
|
<literal>FileSystemResource</literal> or
|
|
<literal>AssemblyResource</literal> 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
|
|
.<literal>ResourceHandlersSectionHandler</literal> or define an object
|
|
of the type
|
|
<literal>Spring.Objects.Factory.Config.ResourceHandlerConfigurer</literal>
|
|
as you would any other Spring managed object. An example of the latter
|
|
is shown below:</para>
|
|
|
|
<programlisting language="myxml"><object id="myResourceHandlers" type="Spring.Objects.Factory.Config.<literal>ResourceHandlersSectionHandler</literal>, Spring.Core">
|
|
<property name="ResourceHandlers">
|
|
<dictionary>
|
|
<entry key="db" value="MyCompany.MyApp.Resources.MyDbResource, MyAssembly"/>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml: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 language="myxml"><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 language="myxml"><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
|
|
<literal>Spring.Objects.Factory.Config.TypeAliasConfigurer</literal>
|
|
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 <literal>TypeAliasConfigurer</literal>
|
|
is shown below</para>
|
|
|
|
<programlisting language="myxml"><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 xml:id="context-type-converters">
|
|
<title>Registering Type Converters</title>
|
|
|
|
<para>The standard .NET mechanism for specifying a type converter is to
|
|
add a <literal>TypeConverter</literal> 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
|
|
<literal>Spring.Objects.Factory.Config.</literal><literal>CustomConverterConfigurer</literal>.
|
|
An example of registration using a
|
|
<literal>CustomConverterConfigurer</literal> is shown below</para>
|
|
|
|
<programlisting language="myxml"><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 xml:id="context-functionality">
|
|
<title>Added functionality of the
|
|
<literal>IApplicationContext</literal></title>
|
|
|
|
<para>As already stated in the previous section, the
|
|
<literal>IApplicationContext</literal> has a couple of features that
|
|
distinguish it from the <literal>IObjectFactory</literal>. Let us review
|
|
them one-by-one.</para>
|
|
|
|
<sect2 xml: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 language="myxml"><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 language="myxml"><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
|
|
<literal>Spring.Context.Support.XmlApplicationContext</literal>. The
|
|
name of the context can be used in conjunction with the service locator
|
|
class, <literal>ContextRegistry</literal>, discussed in <xref
|
|
linkend="objects-servicelocator" /></para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-functionality-messagesource">
|
|
<title>Using <literal>IMessageSource</literal></title>
|
|
|
|
<para>The <literal>IApplicationContext</literal> interface extends an
|
|
interface called <literal>IMessageSource</literal> 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 <literal>IMessageSource</literal> and using
|
|
CurrentUICulture.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, CultureInfo
|
|
cultureInfo)</literal>: retrieves a message from the
|
|
<literal>IMessageSource</literal> using a specified
|
|
culture.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, params object[]
|
|
args)</literal>: retrieves a message from the
|
|
<literal>IMessageSource</literal> 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 <literal>IMessageSource</literal> 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
|
|
<literal>IMessageSource</literal> 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, CultureInfo 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 <literal>IApplicationContext</literal> gets loaded, it
|
|
automatically searches for an <literal>IMessageSource</literal> 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
|
|
<literal>IApplicationContext</literal> checks to see if it has a parent
|
|
containing a similar object, with a similar name. If so, it uses that
|
|
object as the <literal>IMessageSource</literal>. 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>
|
|
|
|
<para>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.</para>
|
|
</warning>
|
|
|
|
<para>Spring.NET provides two <literal>IMessageSource</literal>
|
|
implementations. These are <literal>ResourceSetMessageSource</literal>
|
|
and <literal>StaticMessageSource</literal>. Both implement
|
|
<literal>IHierarchicalMessageSource</literal> to resolve messages
|
|
hierarchically. The <literal>StaticMessageSource</literal> is hardly
|
|
ever used but provides programmatic ways to add messages to the source.
|
|
The <literal>ResourceSetMessageSource</literal> is more interesting and
|
|
an example is provided for in the distribution and discussed more
|
|
extensively in the <xref linkend="quickstarts" /> section. The
|
|
<literal>ResourceSetMessageSource</literal> is configured by providing a
|
|
list of <literal>ResourceManager</literal>s. When a message code is to
|
|
be resolved, the list of ResourceManagers is searched to resolve the
|
|
code. For each <literal>ResourceManager</literal> a
|
|
<literal>ResourceSet</literal> 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
|
|
language="myxml"><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
|
|
<literal>ResourceManagerConverter</literal> TypeConverter. This
|
|
converter can be similarly used to set a property on any object that is
|
|
of the type <literal>ResourceManager.</literal> You may also specify an
|
|
instance of the <literal>ResourceManager</literal> to use via an object
|
|
reference. The convenience class
|
|
<literal>Spring.Objects.Factory.Config.ResourceManagerFactoryObject</literal>
|
|
can be used to conveniently create an instance of a ResourceManager.
|
|
<programlisting language="myxml"><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
|
|
<literal>String.Format</literal> 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 language="csharp">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 <literal>DefaultMessageResolvable</literal> 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
|
|
language="csharp">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 <literal>IMessageSourceAware</literal> interface can also be
|
|
used to acquire a reference to any <literal>IMessageSource</literal>
|
|
that has been defined. Any object that is defined in an
|
|
<literal>IApplicationContext</literal> that implements the
|
|
<literal>IMessageSourceAware</literal> interface will be injected with
|
|
the application context's <literal>IMessageSource</literal> when it (the
|
|
object) is being created and configured.</para>
|
|
</sect2>
|
|
|
|
<sect2 xml: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
|
|
<literal>IApplicationContext</literal> 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 <literal>IResource</literal> abstraction in
|
|
general.</para>
|
|
</sect2>
|
|
|
|
<sect2 xml: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 <literal>Spring.Objects.Events.IEventRegistry</literal>
|
|
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>
|
|
|
|
<listitem>
|
|
<para><literal>void Unsubscribe(object subscriber )</literal>:
|
|
Unsubscribe all events from the source object for which it has
|
|
matching handler methods.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void Unsubscribe(object subscriber, Type
|
|
targetSourceType )</literal>: Unsubscribe all events from a source
|
|
object of a particular type for which it has matching handler
|
|
methods.</para>
|
|
</listitem>
|
|
</itemizedlist> <literal>IApplicationContext</literal> implements this
|
|
interface and delegates the implementation to an instance of
|
|
<literal>Spring.Objects.Events.Support.EventRegistry</literal>. 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,
|
|
<literal>IApplicationContext</literal> 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
|
|
<literal>IApplicationContext</literal> instance. From there, three
|
|
objects are loaded up: one publisher and two subscribers. The publisher
|
|
publishes its events to the <literal>IApplicationContext</literal>
|
|
instance: <programlisting language="csharp">// 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 <literal>IApplicationContext</literal> instance, using
|
|
the publisher type as the filter criteria.<programlisting
|
|
language="csharp">// 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 xml:id="context-functionality-events">
|
|
<title>Event notification from
|
|
<literal>IApplicationContext</literal></title>
|
|
|
|
<para>Event handling in the <literal>IApplicationContext</literal> is
|
|
provided through the <literal>IApplicationListener</literal> interface
|
|
that contains the single method <literal>void OnApplicationEvent( object
|
|
source, ApplicationEventArgs applicationEventArgs )</literal>. Classes
|
|
that implement the <literal>IApplicationListener</literal> interface are
|
|
automatically registered as a listener with the
|
|
<literal>IApplicationContext</literal>. 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, <literal>ApplicationEventArgs</literal>,
|
|
adds the time of the event firing as a property. The derived class
|
|
<literal>ContextEventArgs</literal> 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
|
|
<literal>IApplicationContext</literal> was either initialized or
|
|
refreshed. Initialized here means that all objects are loaded,
|
|
singletons are pre-instantiated and the
|
|
<literal>IApplicationContext</literal> is ready for use. The
|
|
<literal>Closed</literal> is published when the
|
|
<literal>IApplicationContext</literal> is closed using the
|
|
<literal>Dispose()</literal> method on the
|
|
<literal>IConfigurableApplicationContext</literal> 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
|
|
<literal>IApplicationContext</literal>, 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
|
|
<literal>IApplicationContext</literal>: <programlisting
|
|
language="myxml"><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
|
|
language="csharp">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 xml:id="objects-context-customization">
|
|
<title>Customized behavior in the ApplicationContext</title>
|
|
|
|
<para>The <literal>IObjectFactory</literal> already offers a number of
|
|
mechanisms to control the lifecycle of objects deployed in it (such as
|
|
marker interfaces like <literal>IInitializingObject</literal> and
|
|
<literal>System.IDisposable</literal>, 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
|
|
<literal>IApplicationContext</literal>, all of these still work, but
|
|
additional mechanisms are added for customizing behavior of objects and
|
|
the container.</para>
|
|
|
|
<sect2 xml:id="objects-context-applicationcontextaware">
|
|
<title>The <literal>IApplicationContextAware</literal> marker
|
|
interface</title>
|
|
|
|
<para>All marker interfaces available with ObjectFactories still work.
|
|
The <literal>IApplicationContext</literal> 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 xml:id="objects-context-objectpostprocessor">
|
|
<title>The <literal>IObjectPostProcessor</literal></title>
|
|
|
|
<para>Object post-processors are classes which implement the
|
|
<literal>Spring.Objects.Factory.Config.IObjectPostProcessor</literal>
|
|
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 <literal>IApplicationContext</literal>s than
|
|
in plain <literal>IObjectFactory</literal> instances. In an
|
|
<literal>IApplicationContext</literal>, 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 xml:id="objects-context-objectfactorypostprocessor">
|
|
<title>The <literal>IObjectFactoryPostProcessor</literal></title>
|
|
|
|
<para>Object factory post-processors are classes which implement the
|
|
<literal>Spring.Objects.Factory.Config.IObjectFactoryPostProcessor</literal>
|
|
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
|
|
<literal>IApplicationContext</literal>s. In an
|
|
<literal>IApplicationContext</literal>, 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 xml: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
|
|
<literal>IObjectFactory</literal>. It is worth mentioning here though,
|
|
that it is generally more convenient to use it with an
|
|
<literal>IApplicationContext</literal>, 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 language="csharp">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 language="csharp">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 xml: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 <literal>IObjectFactory</literal> or
|
|
<literal>IApplicationContext</literal> 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 <literal>IObjectFactory</literal> or
|
|
<literal>IApplicationContext</literal>. 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 <literal>Spring.Context.Support.ContextRegistry</literal> class
|
|
allows you to obtain a reference to an
|
|
<literal>IApplicationContext</literal> via a static locator method. The
|
|
<literal>ContextRegistry</literal> is initialized when creating an
|
|
<literal>IApplicationContext</literal> through use of the
|
|
<literal>ContextHandler</literal> discussed previously. The simple static
|
|
method <literal>GetContext()</literal> can then be used to retrieve the
|
|
context. Alternatively, if you create an
|
|
<literal>IApplicationContext</literal> though other means you can register
|
|
it with the <literal>ContextRegistry</literal> 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 language="csharp">IApplicationContex ctx = ContextRegistry.GetContext("mySubContext");</programlisting>
|
|
This would retrieve the nested context for the context configuration shown
|
|
previously.<programlisting language="myxml"><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>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Stereotype attributes</title>
|
|
|
|
<para>Beginning with Spring 1.2, the [Repository] attribute was introduced
|
|
as a marker for any class that fulfills the role or stereotype of a
|
|
repository (a.k.a. Data Access Object or DAO). Among the possibilities for
|
|
leveraging such a marker is the automatic translation of exceptions as
|
|
described in <link linkend="orm-hibernate-straight-ex">Exception
|
|
Translation.</link></para>
|
|
|
|
<para>Spring 1.2 introduces further stereotype annotations: [Component]
|
|
and [Service]. [Component] serves as a generic stereotype for any
|
|
Spring-managed component; whereas, [Repository] and [Service] serve as
|
|
specializations of [Component] for more specific use cases (e.g., in the
|
|
persistence and service layers, respectively). The ASP.NET MVC
|
|
[Controller] attribute will serve this purpose for the controller layer.
|
|
What this means is that you can annotate your component classes with
|
|
[Component], but by annotating them with [Repository] or [Service] your
|
|
classes are more properly suited for processing by tools or associating
|
|
with aspects. For example, these stereotype annotations make ideal targets
|
|
for pointcuts. Of course, it is also possible that [Repository] and
|
|
[Service] may carry additional semantics in future releases of the Spring
|
|
Framework. Thus, if you are making a decision between using [Component] or
|
|
[Service] for your service layer, [Service] is clearly the better choice.
|
|
Similarly, as stated above, [Repository] is already supported as a marker
|
|
for automatic exception translation in your persistence layer. The next
|
|
version of Spring will use the [Component] attribute to perform attribute
|
|
based autowiring by-type as in the Spring Java Framework.</para>
|
|
</sect1>
|
|
</chapter>
|