Files
spring-net/doc/reference/src/objects.xml

6478 lines
309 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
* Copyright 2002-2010 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 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 is the basis for
Spring.NET's IoC container. The <literal><link
ns6:href="http://www.springframework.net/doc-latest/api/net-2.0/html/Spring.Core~Spring.Objects.Factory.IObjectFactory.html">IObjectFactory</link></literal>
interface provides an advanced configuration mechanism capable of managing
any type of object. <literal><link
ns6:href="http://www.springframework.net/doc-latest/api/net-2.0/html/Spring.Core~Spring.Context.IApplicationContext.html">IApplicationContext</link></literal>
is a sub-interface of <literal>IObjectFactory</literal>. It adds 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, and the
<literal>IApplicationContext</literal> adds more enterprise-specific
functionality. The <literal>IApplicationContext</literal> is a complete
superset of the <literal>IObjectFactory</literal> and is used exclusively
in this chapter in descriptions of Spring's IoC container.</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>Container overview</title>
<para>The interface <classname>IApplicationContext</classname> represents
the Spring IoC container and is responsible for instantiating,
configuring, and assembling many of the objects in your application. The
container gets its instructions on what objects to instantiate, configure,
and assemble by reading configuration metadata. The configuration metadata
is represented in XML. The configuration metadata allows you to express
the objects that compose your application and the rich interdependencies
between such objects.</para>
<note>
<para>Note that other ways to specify the metadata, such as attributes
and .NET code, are planned for future releases, the core IoC container
does not assume any specific metadata format. The Java version of Spring
already supports such functionality.</para>
</note>
<para>Several implementations of the
<classname>IApplicationContext</classname> interface are supplied
out-of-the-box with Spring. In standalone applications it is common to
create an instance of an <classname>XmlApplicationContext</classname>
either programmatically or declaratively in your applications App.config
file. In web applications Spring provides a
<classname>WebApplicationContext</classname> implementation which is
configured by adding a custom HTTP module and HTTP handler to your
Web.config file. See the section on <link linkend="web-configuration">Web
Configuration</link> for more details.</para>
<para>The following diagram is a high-level view of how Spring works. Your
application classes are combined with configuration metadata so that after
the ApplicationContext is created and initialized, you have a fully
configured and executable system or application.</para>
<mediaobject>
<imageobject>
<imagedata fileref="images/container-in-action.gif" format="GIF"></imagedata>
</imageobject>
</mediaobject>
<sect2 xml:id="objects-configuration-metadata">
<title>Configuration metadata</title>
<para>As the preceding diagram shows, the Spring IoC container consumes
a form of <emphasis>configuration metadata</emphasis>; this
configuration metadata represents how you as an application developer
tell the Spring container to instantiate, configure, and assemble the
objects in your application. Configuration metadata is supplied in a
simple and intuitive XML format</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 and code
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 and typically more
than one object definition that the container must manage. XML- based
configuration shows these objects as <literal>&lt;object/&gt;</literal>
elements inside a top-level &lt;objects/&gt; element.</para>
<para>These object definitions correspond to the actual objects that
make up your application. Typically you define service layer objects,
data access objects (DAOs), presentation objects such as ASP.NET page
instances, infrastructure objects such as NHibernate
<literal>SessionFactories</literal>, 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>The following example shows the basic structure of XML-based
configuration metadata:</para>
<programlisting language="myxml">&lt;objects xmlns="http://www.springframework.net"&gt;
&lt;object id="..." type="..."&gt;
&lt;!-- collaborators and configuration for this object go here --&gt;
&lt;/object&gt;
&lt;object id="...." type="..."&gt;
&lt;!-- collaborators and configuration for this object go here --&gt;
&lt;/object&gt;
&lt;!-- more object definitions go here --&gt;
&lt;/objects&gt;</programlisting>
<para>The <literal>id</literal> attribute is a string that you use to
identify the individual object definition. The type attribute defines
the type of the object and uses the fully qualified type name, including
the assembly name. The value of the <literal>id</literal> attribute
refers to collaborating objects. The XML for referring to collaborating
objects is not shown in this example; <link
linkend="objects-dependencies">Dependencies</link> for more
information.</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>
</sect2>
<sect2 xml:id="objects-factory-instantiation">
<title>Instantiating a container</title>
<para>Instantiating a Spring IoC container is straightforward. The
location path or paths suppied to an IApplicationContext constructor are
actually resource strings that allow the container to load configuration
metadata from a variety of external resources such as the local file
system, embedded assembly resources, and so on.</para>
<programlisting language="csharp">IApplicationContext context = new XmlApplicationContext("services.xml", "data-access.xml");
</programlisting>
<para>The following example shows the service layer objects
<literal>(services.xml)</literal> configuration file.</para>
<para><programlisting language="myxml">&lt;objects xmlns="http://www.springframework.net"&gt;
&lt;object id="PetStore" type="PetStore.Services.PetStoreService, PetStore"&gt;
&lt;property name="AccountDao" ref="AccountDao"/&gt;
&lt;property name="ItemDao" ref="ItemDao"/&gt;
&lt;!-- additional collaborators and configuration for this object go here --&gt;
&lt;/object&gt;
&lt;!-- more object definitions for services go here --&gt;
&lt;/objects&gt;</programlisting>The following example shows the data access
objects <literal>(daos.xml)</literal> configuration file:</para>
<programlisting language="myxml">&lt;objects xmlns="http://www.springframework.net"&gt;
&lt;object id="AccountDao" type="Petstore.Dao.HibernateAccountDao, PetStore"&gt;
&lt;!-- additional collaborators and configuration for this object go here --&gt;
&lt;/object&gt;
&lt;object id="ItemDao" type="Petstore.Dao.HibernateItemDao, PetStore"&gt;
&lt;!-- additional collaborators and configuration for this object go here --&gt;
&lt;/object&gt;
&lt;!-- more object definitions for data access objects go here --&gt;
&lt;/objects&gt;</programlisting>
<para>In the preceeding example, the service layer consists of the class
<classname>PetStoreService</classname>, and two data access objects of
the type <classname>HibernateAccountDao</classname> and
<classname>HibernateItemDao</classname> are based on the NHibernate
Object/Relational mapping framework. The property name element refers to
the name of the class's property, and the ref element refers to the name
of another object definition. This linkage between id and ref elements
expresses the dependency between collaborating objects. For details of
configuring an object's dependencies, see <link
linkend="objects-dependencies">Dependencies</link>.</para>
<sect3>
<title>Loading configuration metadata from non-default resource
locations</title>
<para>In the previous example the configuration resources are assumed
to be located in the bin\Debug directory. You can use Spring's
<classname><link
ns6:href="http://www.springframework.net/doc-latest/api/net-2.0/html/Spring.Core~Spring.Core.IO.IResource.html">IResource</link></classname>
abstraction to load resources from other locations.</para>
<para>The following example shows how to create an IoC container
referring to resources located in the root directory of the filesystem
an as an embedded assembly resource.</para>
<para><programlisting language="csharp">IApplicationContext context = new XmlApplicationContext(
"file:///services.xml",
"assembly://MyAssembly/MyDataAccess/data-access.xml");
</programlisting>The above example uses Spring.NET's <classname><link
ns6:href="http://www.springframework.net/doc-latest/api/net-2.0/html/Spring.Core~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>.</para>
<note>
<para>After you learn about Spring's IoC container, you may want to
know more about Spring's <classname><link
ns6:href="http://www.springframework.net/doc-latest/api/net-2.0/html/Spring.Core~Spring.Core.IO.IResource.html">IResource</link></classname>
abstraction to load metadata from other locations as desribed below
and alsoin the chapter <xref linkend="resources" /></para>
</note>
<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:///services.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://&lt;AssemblyName&gt;/&lt;NameSpace&gt;/&lt;ResourceName&gt;</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 &lt;resources&gt; section to the csc task. For
example usage, look at the Spring.Core.Tests.build file included the
distribution.</para>
</note>
</sect3>
<sect3>
<title>Declarative configuration of the container in
App.config/Web.config</title>
<para>You can also create a container by using 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">&lt;spring&gt;
&lt;context&gt;
&lt;resource uri="file://services.xml"/&gt;
&lt;resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/&gt;
&lt;/context&gt;
&lt;/spring&gt; </programlisting>The context type (specified as the value of
the <literal>type</literal> attribute of the
<literal>context</literal> element) is optional. In a standalone
application the context type defaults to the
<literal>Spring.Context.Support.XmlApplicationContext</literal> class
and in a Web application defaults to WebApplicationContext. An example
of explicitly configuring the context type The following example shows
explicit use of the context type attribute: <programlisting
language="myxml">&lt;spring&gt;
&lt;context type="Spring.Context.Support.XmlApplicationContext, Spring.Core"&gt;
&lt;resource uri="file:///services.xml"/&gt;
&lt;resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/&gt;
&lt;/context&gt;
&lt;/spring&gt;</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">&lt;configSections&gt;
&lt;sectionGroup name="spring"&gt;
&lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&gt;
&lt;/sectionGroup&gt;
&lt;/configSections&gt; </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
<literal>IApplicationContext</literal> interface, since Spring.NET
code will do it for you. For example, the ASP.NET web layer provides
support code to load a Spring.NET
<literal>WebApplicationContext</literal> automatically as part of the
normal startup process of an ASP.NET web application. As such, once
the container has been created for you, it is often the case that you
will never need to explicitly interact with it again in your code, for
example when configuring ASP.NET pages.</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">&lt;configuration&gt;
&lt;configSections&gt;
&lt;sectionGroup name="spring"&gt;
&lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&gt;
&lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /&gt;
&lt;/sectionGroup&gt;
&lt;/configSections&gt;
&lt;spring&gt;
&lt;context&gt;
&lt;resource uri="config://spring/objects"/&gt;
&lt;/context&gt;
&lt;objects xmlns="http://www.springframework.net"&gt;
...
&lt;/objects&gt;
&lt;/spring&gt;
&lt;/configuration&gt;</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>
<sect3 xml:id="objects-factory-xml-import">
<title>Composing XML-based configuration metadata</title>
<para>It can be useful to have object definitions span multiple XML
files. Often each individual XML configuration file represents a
logical layer or module in your architecture.</para>
<para>You can use the <classname>IApplicationContext</classname>
constructor to load object definitions from all these XML fragments.
This constructor takes multiple <classname>IResource</classname>
locations, as was shown in the previous section. Alternatively, use
one or more occurrences of the <literal>&lt;import/&gt;</literal>
element to load object definitions from another file (or files). For
example:</para>
<para><programlisting language="myxml">&lt;objects xmlns="http://www.springframework.net"&gt;
&lt;import resource="services.xml"/&gt;
&lt;import resource="resources/messageSource.xml"/&gt;
&lt;import resource="/resources/themeSource.xml"/&gt;
&lt;object id="object1" type="..."/&gt;
&lt;object id="object2" type="..."/&gt;
&lt;/objects&gt;</programlisting></para>
<para>In the preceeding example, external object definitions are being
loaded from three files, <literal>services.xml</literal>,
<literal>messageSource.xml</literal>, and
<literal>themeSource.xml</literal>. All location paths are relative to
the definition file doing the importing, so
<literal>services.xml</literal> 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 ignored, but given
that these paths are relative, it is better form not to use the slash
at all. The contents of the files being imported, including the top
level <literal>&lt;objects/&gt;</literal> element, must be valid XML
object definitions according to the Spring Schema.</para>
</sect3>
</sect2>
<sect2 xml:id="objects-factory-client">
<title>Using the container</title>
<para>An <literal>IApplicationContext</literal> is the interface for an
advanced factory capable of maintaining a registry of different objects
and their dependencies. Using the method
<literal>GetObject(string)</literal> or the indexer
<literal>[string]</literal> you can retrieve instances of your
objects.</para>
<para>The <literal>IApplicationContext</literal> enables you to read
object definitions and access them as follows:</para>
<programlisting language="csharp">// create and configure objects
IApplicationContext context = new XmlApplicationContext("services.xml", "daos.xml");
// retrieve configured instance
PetStoreService service = (PetStoreService) context.GetObject("PetStoreService");
// use configured instance
IList userList = service.GetUserNames();
</programlisting>
<para>You use the method <literal>GetObject</literal> to retrieve
instances of your objects. The IApplicationContext interface has a few
other methods for retrieving objects, but ideally your application code
should never use them. Indeed, your application code should have no
calls to the GetObject method at all, and thus no dependency on Spring
APIs at all. For example, Spring's integration with web frameworks
provides for dependency injection for various web framework classes such
as ASP.NET pages and user controls.</para>
<note>
<para>The syntactical inconvenience of the cast will be addressed in a
future release of Spring.NET that is based on a generic API. Note,
that even when using a generic API, looking up an object by name in no
way guarantees that the return type will be that of the generic
type.</para>
</note>
</sect2>
<sect2 xml:id="objects-definition">
<title>Object definition overview</title>
<para>A Spring IoC container manages one or more objects. These objects
are created with the configuration metadata that you supply to the
container.</para>
<para>Within the container itself, these object definitions are
represented as <classname>IObjectDefinition</classname> objects, which
contain (among other information) the following metadata: <itemizedlist
spacing="compact">
<listitem>
<para><emphasis>A type name</emphasis>: typically 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 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>This metadata translates to a set of properties that make up each
object definition. The following table lists some of these properties,
with links to documentation <table frame="all">
<title>Object definition explanation</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<thead>
<row>
<entry>Property</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>In addition to object definitions which contain information on how
to create a specific object, the
<classname>IApplicationContext</classname> implementations also permit
the registration of existing objects that are created outside the
container, by users. This is done by accessing the
<classname>ApplicationContext's</classname>
<classname>IObjectFactory</classname> via the property
<literal>ObjectFactory</literal> which returns the
<classname>IObjectFactory</classname> implementation
<classname>DefaultListableObjectFactory</classname>.
<classname>DefaultListableObjectFactory</classname> supports
registration through the methods
<literal>RegisterSingleton(..)</literal> and
<literal>RegisterObjectDefinition(..)</literal>. However, typical
applications work soley with objects defined through metadata object
definitions.</para>
<sect3 xml:id="objects-objectname">
<title>Naming objects</title>
<para>Every object has one or more identifiers. These identifiers must
be unique within the container that hosts the objects. An object
usually has only one identifier, but if it requires more than one, the
extra ones can be considered aliases.</para>
<sidebar>
<para>A convention that has evolved is to use the standard C#
convention for Property names when naming objects. That is, object
names start with a uppercase letter, and are camel-cased from then
on. Examples of such names would be (without quotes)
'AccountManager', 'AccountService', 'UserDao', 'LoginController',
and so forth.</para>
<para>Naming object consistently makes your configuration easier to
read and understand, and if you are using Spring AOP it helps a lot
when applying advice to a set of objects related by name.</para>
</sidebar>
<para>When using XML-based configuration metadata, you use the
<literal>'id'</literal> and/or <literal>'name'</literal>attributes to
specify the object identifier(s). The <literal>'id'</literal>
attribute allows you to specify exactly one id, and because 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
can specify them in the <literal>'name'</literal> attribute ,
separated by a comma (<literal>,</literal>), semicolon
(<literal>;</literal>), or whitespace.</para>
<note>
<para>You are not required to supply a name or id for a object. If
no name or id is supplied explicitly, the container will generate a
unique name for that object. However, if you want to refer to that
object by name, through the use of the ref element or Service
Location style lookup, you must provide a name. The motivations for
not supplying a name for a object are to use <link
linkend="objects-factory-autowire">autowiring</link> and <link
linkend="objects-inline-object">inline-objects</link> which will be
discussed later.</para>
</note>
<sect4>
<title>Aliasing an object outside the object definition</title>
<para>In an object definition itself, you may supply more than one
name for the object, by using a combination of up to one name
specified by the <literal>id</literal> attribute, and any number of
other names in the <literal>name</literal> attribute. These names
are equivalent aliases to the same object, and are useful for some
situations, such as allowing each component in an application to
refer to a common dependency by using a object name that is specific
to that component itself.</para>
<para>Specifying all aliases where the object is actually defined is
not always adequate, however. It is sometimes desirable to introduce
an alias for an object that is defined elsewhere. This is commonly
the case in large systems where configuration is split amongst each
subsystem, each subsystem having its own set of object defintions.
In XML-based configuration metadata, you can use of the
&lt;alias/&gt; element to accomplish this.</para>
<programlisting language="myxml"> &lt;alias name="fromName" alias="toName"/&gt;</programlisting>
<para>In this case, an object in the same container which is named
<literal>fromName</literal>, may also after the use of this alias
definition, be referred to as <literal>toName</literal>.</para>
<para>For example, the configuration metadata for subsystem A may
refer to a DbProvider via the name 'SubsystemA-DbProvider. The
configuration metadata for subsystem B may refer to a DbProvider via
the name 'SubsystemB-DbProvider'. When composing the main
application that uses both these subsystems the main application
refers to the DbProvider via the name 'MyApp-DbProvider'. To have
all three names refer to the same object you add to the MyApp
configuration metadata the following aliases definitions:</para>
<programlisting language="myxml">&lt;alias name="SubsystemA-DbProvider" alias="SubsystemB-DbProvider"/&gt;
&lt;alias name="SubsystemA-DbProvider" alias="MyApp-DbProvider"/&gt;</programlisting>
<para>Now each component and the main app can refer to the
connection through 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>Instantiating objects</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 in the
<literal>'type'</literal> attribute of the
<literal>&lt;object/&gt;</literal> element. This
<literal>'type'</literal> attribute (which internally is a
<literal>Type</literal> property on a
<literal>IObjectDefinition</literal> instance) is usually mandatory.
(For exceptions see the section called <link
linkend="objects-factory-class-instance-factory-method">Instantiation
using an instance factory method </link>and <link
linkend="objects-childobjects">Object definition inheritance</link>.)
You use the Type property in one of two ways:</para>
<itemizedlist>
<listitem>
<para>Typically, to specify the type of of the object to be
constructed in the 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.</para>
</listitem>
<listitem>
<para>To specify the actual class containing the
<literal>static</literal> factory method that will be invoked to
create the object, 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 object type returned
from the invocation of the <literal>static</literal> factory method
may be the same type or another type entirely.</para>
</listitem>
</itemizedlist>
<sect3 xml:id="objects-factory-class-ctor">
<title>Instantiatoin with a constructor</title>
<para>When you create an object using the constructor approach, all
normal classes are usable by and compatible with Spring. That is, the
class being developed does not need to implement any specific
interfaces or to be coded in a specific fashion. Simply specifying the
object type should be sufficient. However, depending on what type of
IoC you are going to use for that specific object, you may need to
create a default constructor.</para>
<para>With XML-based configuration metadata you can specify your
object class as follows: <programlisting language="myxml">&lt;object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/&gt;</programlisting></para>
<para>For details about the mechanism for supplying arguments to the
constructor (if required), and setting object instance properties
after the object is constructed, see <xref
linkend="objects-factory-collaborators" />.</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">&lt;object id="exampleObject" type="Examples.ExampleObject+Person, ExamplesLibrary"/&gt;</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>&lt;object/&gt;</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>Instantiation with a static factory method</title>
<para>When defining an object which is to be created using a static
factory method, you use the type attribute to specify the type
containing the static factory method and an attribute named
factory-method to specify the name of the factory method itself. You
should be able to call this method (with an optional list of arguments
as described later) and return a live object, which subsequently is
treated as if it had been created through a constructor. One use for
such an object definition is to call static factories in legacy
code.</para>
<para>The following object definition specifies that the object will
be created by calling a factory-method. The definition does not
specify the type 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">&lt;object id="exampleObject"
type="Examples.ExampleObjectFactory, ExamplesLibrary"
factory-method="CreateInstance"/&gt;</programlisting></para>
<para>For details about the mechanism for supplying (optional)
arguments to the factory method and setting object instance properties
after it has been returned from the factory, see <xref
linkend="object-factory-properties-detailed" /></para>
</sect3>
<sect3 xml:id="objects-factory-class-instance-factory-method">
<title>Object creation via an instance factory method</title>
<para>Similar to instantiation through a <link
linkend="objects-factory-class-static-factory-method">static factory
method</link>, instantiation with an instance factory method invokes a
a non-static method on an existing object from the container to create
a new object. To use this mechanism, leave the <literal>type</literal>
attribute empty, and in the <literal>factory-object</literal>
attribute 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. Set the name of the factory method
itself with the <literal>factory-method</literal>
attribute.<programlisting language="myxml">&lt;!-- the factory object, which contains an instance method called 'CreateInstance' --&gt;
&lt;object id="exampleFactory" type="..."&gt;
&lt;!-- inject any dependencies required by this object --&gt;
&lt;/object&gt;
&lt;!-- the object that is to be created by the factory object --&gt;
&lt;object id="exampleObject"
factory-method="CreateInstance"
factory-object="exampleFactory"/&gt;</programlisting></para>
<para>This approach shows that the factory object itself can be
managed and configured through dependency injection (DI). See <link
linkend="object-factory-properties-detailed">Dependencies and
configuraiton in detail</link>.<note>
<para>In Spring documentation, '<emphasis>factory
object</emphasis>', refers to an object that is configured in the
Spring container that will create objects via an <link
linkend="objects-factory-class-instance-factory-method">instance</link>
or <link
linkend="objects-factory-class-static-factory-method">static</link>
factory method. By contrast, <literal>IFactoryObject</literal>
(notice the capitalization) refers 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&lt;T&gt;
{
private List&lt;T&gt; list;
private String name;
public List&lt;T&gt; Contents
{
get { return list; }
set { list = value; }
}
public String Name
{
get { return name; }
set { name = value; }
}
public List&lt;T&gt; ApplyFilter(string filterExpression)
{
/// should really apply filter to list ;)
return new List&lt;T&gt;();
}
}
}</programlisting> The XML configuration to create and configure this object
is shown below <programlisting language="myxml">&lt;object id="myFilteredIntList" type="GenericsPlay.FilterableList&amp;lt;int&gt;, GenericsPlay"&gt;
&lt;property name="Name" value="My Integer List"/&gt;
&lt;/object&gt;</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>&lt;</literal>, is replaced with the
string &amp;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">&lt;typeAliases&gt;
&lt;alias name="GenericDictionary" type=" System.Collections.Generic.Dictionary&amp;lt;,&gt;" /&gt;
&lt;alias name="myDictionary" type="System.Collections.Generic.Dictionary&amp;lt;int,string&gt;" /&gt;
&lt;/typeAliases&gt;
</programlisting> So that instead of something like this <programlisting
language="myxml">&lt;object id="myGenericObject"
type="GenericsPlay.ExampleGenericObject&amp;lt;System.Collections.Generic.Dictionary&amp;lt;int , string&gt;&gt;, GenericsPlay" /&gt;</programlisting>
It can be shortened to <programlisting language="myxml">&lt;object id="myOtherGenericObject"
type="GenericsPlay.ExampleGenericObject&amp;lt;GenericDictionary&amp;lt;int , string&gt;&gt;, GenericsPlay" /&gt;</programlisting>
or even shorter <programlisting language="myxml">&lt;object id="myOtherOtherGenericObject"
type="GenericsPlay.ExampleGenericObject&amp;lt;MyIntStringDictionary&gt;, GenericsPlay" /&gt;
</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&lt;T, U&gt;
{
public TestGenericObject()
{
}
private IList&lt;T&gt; someGenericList = new List&lt;T&gt;();
private IDictionary&lt;string, U&gt; someStringKeyedDictionary =
new Dictionary&lt;string, U&gt;();
public IList&lt;T&gt; SomeGenericList
{
get { return someGenericList; }
set { someGenericList = value; }
}
public IDictionary&lt;string, U&gt; SomeStringKeyedDictionary
{
get { return someStringKeyedDictionary; }
set { someStringKeyedDictionary = value; }
}
}</programlisting> The accompanying factory class is <programlisting
language="csharp">
public class TestGenericObjectFactory
{
public static TestGenericObject&lt;V, W&gt; StaticCreateInstance&lt;V, W&gt;()
{
return new TestGenericObject&lt;V, W&gt;();
}
public TestGenericObject&lt;V, W&gt; CreateInstance&lt;V, W&gt;()
{
return new TestGenericObject&lt;V, W&gt;();
}
}
</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">&lt;object id="myTestGenericObject"
type="GenericsPlay.TestGenericObjectFactory, GenericsPlay"
factory-method="StaticCreateInstance&amp;lt;System.Collections.Generic.List&amp;lt;int&gt;,int&gt;"
/&gt;</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">&lt;object id="exampleFactory" type="GenericsPlay.TestGenericObject&amp;lt;int,string&gt;, GenericsPlay"/&gt;
&lt;object id="anotherTestGenericObject"
factory-object="exampleFactory"
factory-method="CreateInstance&amp;lt;System.Collections.Generic.List&amp;lt;int&gt;,int&gt;"/&gt;
</programlisting> This creates an instance of
<literal>TestGenericObject&lt;List&lt;int&gt;,int&gt;</literal></para>
</sect3>
</sect2>
</sect1>
<sect1 xml:id="objects-dependencies">
<title>Dependencies</title>
<para>A typical enterprise application does not consist of a single
object. Even the simplest application has a few 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 to a fully realized application where objects collaborate
to achieve a goal.</para>
<sect2 xml:id="objects-factory-collaborators">
<title>Dependency injection</title>
<para>Dependency injection (DI) is a process whereby objects define
their dependencies, that is, the other objects they work with, only
through constructor arguments and properties that are set on the object
instance after it is constructed. (Factory methods may be considered a
special case of providing constructor arguments for the purposes of this
description). The container injects these dependencies when it creates
the object. This process is fundamentally the inverse to the case when
the object itself is controlling the instantiation or location of its
dependencies by using direct construction of classes, or the Service
Locator pattern. The inverting of this responsibility is why the name
Inversion of Control (IoC) is used to describe the container's
actions.</para>
<para>Code is cleaner when using DI and decoupling is more effective
when objects are provided with their dependencies. The object does not
look up its dependencies, and does not know the location or class of the
dependencies. Long sections of initialization code that you used to hide
in a #region tag simply go away, and are placed by container
configuration metadata. One can also consider this clean up an
application of the principal of Separation of Concerns. Before using DI,
you class was responsible for business logic AND its configuration, it
was concerns with doing more than one thing. DI removes the
responsibility of configuration from the class, leaving it only with a
single purpose, as the location of business logic. Furthermore, since
you class does not know the location of its dependencies these classes
also become easier to test, in particular when the dependencies are
interfaces or abstract base classes allowing for stub or mock
implementation to be used in unit tests.</para>
<para>Dependency injection exists in two major variants,
Constructor-based dependency injection and Setter-based dependency
injection.</para>
<sect3 xml:id="objects-ctor-injection">
<title>Constructor-based dependency injection</title>
<para>Constructor-based DI is accomplished by the container invoking a
constructor with a number of arguments, each representing a
dependency. Calling a static factory method with specific arguments to
construct the object is nearly equivalent, and this discussion treats
arguments to a constructor and to a static factory method similarly.
The following example shows a class that can only be
dependency-injected with constructor injection. Notice that there is
nothing special about this class (no container specific interfaces,
base classes or attributes)</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 ambiguity exists 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 are supplied to the appropriate constructor when the
object being instantiated. Consider the following class:</para>
<programlisting language="csharp">namespace X.Y
{
public class Foo
{
public Foo(Bar bar, Baz baz)
{
// ...
}
}
}</programlisting>
<para>No potential ambiguity exists, assuming of course that Bar and
Baz classes are not related by inheritance. Thus the following
configuration will work just fine, and you do not need to specify
the constructor argument indexes and / or types explicitly in the
<literal>&lt;contructor-arg/&gt;</literal> element.</para>
<programlisting language="myxml">&lt;object id="foo" type="X.Y.Foo, Example"&gt;
&lt;constructor-arg ref="bar"/&gt;
&lt;constructor-arg ref="baz"/&gt;
&lt;/object&gt;
&lt;object id="bar" type="X.Y.Bar, Example"/&gt;
&lt;object id="baz" type="X.Y.Baz, Example"/&gt;
</programlisting>
<para>When another object is referenced, the type is known, and
matching can occur (as was the case with the preceding
example).</para>
<para>When a simple type is used, such as
<literal>&lt;value&gt;true&lt;value&gt;</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>In the preceding scenario, the container
<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">&lt;object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"&gt;
&lt;constructor-arg type="int" value="7500000"/&gt;
&lt;constructor-arg type="string" value="42"/&gt;
&lt;/object&gt;</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>Use the <literal>index</literal> attribute to specify
explicitly the index of constructor arguments. For example:</para>
<para><programlisting language="myxml">&lt;object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"&gt;
&lt;constructor-arg index="0" value="7500000"/&gt;
&lt;constructor-arg index="1" value="42"/&gt;
&lt;/object&gt;</programlisting>In addition to resolving the ambiguity of
multiple simple values, specifying an index also resolves
ambiguity where a constructor has 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>You can specify constructor argumetn by name using
<literal>name</literal> attribute of the
<literal>&lt;constructor-arg&gt;</literal> element.</para>
<programlisting language="myxml">&lt;object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"&gt;
&lt;constructor-arg name="years" value="7500000"/&gt;
&lt;constructor-arg name="ultimateAnswer" value="42"/&gt;
&lt;/object&gt;</programlisting>
</sect5>
</sect4>
</sect3>
<sect3 xml:id="objects-setter-injection">
<title>Setter-based dependency injection</title>
<para>Setter-based DI is accomplished by the container invoking setter
properties on your objects after invoking a no-argument constructor or
no-argument static factory method to instantiate your object.</para>
<para>The following eample shows 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-based 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 properties also makes objects of that class amenable to
reconfigured or reinjection later. Managment through WMI is a
compelling use case.</para>
<para>Some purists favor constructor-based injection. Supplying all
object dependencies means that the object is always returned to
client (calling) code in a totally initialized state. The
disadvantage is that the object becomes less amenable to
reconfiguration and re-injection.</para>
<para>Use the DI that 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 is made for you. A legacy class may not
expose any setter methods, and so constructor injection is the only
available DI.</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>IAppliationContext</literal> supports constructor-
and setter-based DI for the objects it manages. It also supports
setter-based DI after some dependencies have already been supplied via
the constructor approach..</para>
<para>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. 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>
<para>The container resolves object dependeices as: <orderedlist
spacing="compact">
<listitem>
<para>The <literal>IApplicationContext</literal> is created and
initialized with a configuration that 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 if you are using that instead of a normal
constructor. These dependencies apre 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.</para>
</listitem>
</orderedlist></para>
<para>The Spring container validates the configuration of each object
as the container is created, including the validation of whether
object reference properties refer to valid object. However, the object
properties themselves are not set until the object is actually
created. Objects that are defined as singletons and set to be
pre-instantiated, are created when the container is created.
Otherwise, the object is created only when it is requested. Creation
of an object potentially causes a graph of objects to be created as
the objects 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 create unresolvable circular dependency scenario.</para>
<para>For example: 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 objects for classes A and B to be injected into each
other, the Spring IoC container detects 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. Alternatively, avoid constructor injection and stick
to setter injection only. In other words, although it is not
recommended, you can 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
detects configuration problems, such as references to non-existent
object definitions and circular dependencies, at container load-time.
Spring sets properties and resolves 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. For example, the object throws an
exception as a result of a missing or invalid property. This
potentially delayed visibility of some configuration issues is why
<literal>IApplicationContext</literal> by default pre-instantiate
singleton objects. At the cost of some upfront time and memory to
create these objects before they are actually needed, you discover
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 will
lazy-initialize, rather than be pre-instantiated.</para>
<para>If no circular dependencies exist, when one or more
collaborating objects are being injected into a dependent object, each
collaborating object is <emphasis>totally</emphasis> configured prior
to being passed into the dependent object. This means that if object A
has a dependency on object B, the Spring IoC container completely
configures object B prior to invoking the setter method on object A.
In other words, the object is instantiated (if not a pre-instantiated
singleton), its dependencies are 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>Examples of dependency injection</title>
<para>First, an example of using XML-based configuration metadata for
setter-based DI. A small part of a Spring XML configuration file
specifying some object definitions:<programlisting language="myxml">&lt;object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"&gt;
&lt;!-- setter injection using the ref attribute --&gt;
&lt;property name="objectOne" ref="anotherExampleObject"/&gt;
&lt;property name="objectTwo" ref="yetAnotherObject"/&gt;
&lt;property name="IntegerProperty" value="1"/&gt;
&lt;/object&gt;
&lt;object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/&gt;
&lt;object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/&gt;</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>In the preceding example, 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">&lt;object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"&gt;
&lt;constructor-arg name="objectOne" ref="anotherExampleObject"/&gt;
&lt;constructor-arg name="objectTwo" ref="yetAnotherObject"/&gt;
&lt;constructor-arg name="IntegerProperty" value="1"/&gt;
&lt;/object&gt;
&lt;object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/&gt;
&lt;object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/&gt;</programlisting>
<programlisting language="vb">[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>Ghe 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">&lt;object id="exampleObject" type="Examples.ExampleFactoryMethodObject, ExamplesLibrary"
factory-method="CreateInstance"&gt;
&lt;constructor-arg name="objectOne" ref="anotherExampleObject"/&gt;
&lt;constructor-arg name="objectTwo" ref="yetAnotherObject"/&gt;
&lt;constructor-arg name="intProp" value="1"/&gt;
&lt;/object&gt;
&lt;object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/&gt;
&lt;object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/&gt;</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>Arguments to the static factory method are supplied via
<literal>&lt;constructor-arg/&gt;</literal> elements, exactly the same
as if a constructor had actually been used. 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 would
be used in an essentially identical fashion (aside from the use of the
<literal>factory-object</literal> attribute instead of the
<literal>type</literal> 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">&lt;object id="exampleObject" type="Examples.MixedIocObject, ExamplesLibrary"&gt;
&lt;constructor-arg name="objectOne" ref="anotherExampleObject"/&gt;
&lt;property name="objectTwo" ref="yetAnotherObject"/&gt;
&lt;property name="IntegerProperty" value="1"/&gt;
&lt;/object&gt;
&lt;object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/&gt;
&lt;object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/&gt;</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, you can define object
properties and constructor arguments as either references to other
managed objects (collaborators), or as values defined inline. Spring's
XML-based configuration metadata supports sub-element types within its
<literal>&lt;property/&gt;</literal> and
&lt;<literal>constructor-arg/&gt;</literal> elements for this
purpose.</para>
<sect3 xml:id="objects-simple-values">
<title>Straight values (primitives, <literal>strings</literal>, and so
on)</title>
<para>The <literal>value</literal> attribute of the
<literal>&lt;property/&gt;</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.</para>
<para>In the following example, we use a
<literal>SqlConnection</literal> from the
<literal>System.Data.SqlClient</literal> namespace. This class (like
many other existing classes) can easily configured by Spring as it
offers a convenient public property for configuration of its
<literal>ConnectionString</literal> property.</para>
<para><programlisting language="myxml">&lt;objects xmlns="http://www.springframework.net"&gt;
&lt;object id="myConnection" type="System.Data.SqlClient.SqlConnection"&gt;
&lt;!-- results in a call to the setter of the ConnectionString property --&gt;
&lt;property
name="ConnectionString"
value="Integrated Security=SSPI;database=northwind;server=mySQLServer"/&gt;
&lt;/object&gt;
&lt;/objects&gt;</programlisting></para>
<sect4>
<title>The idref element</title>
<para>An idref element is simply an error-proof way to pass the
<emphasis>id</emphasis> (string value - not a reference) of another
object in the container to a
<literal>&lt;constructor-arg/&gt;</literal> or
<literal>&lt;property/&gt;</literal> element.<programlisting
language="myxml">&lt;object id="theTargetObject" type="..."&gt;
. . .
&lt;/object&gt;
&lt;object id="theClientObject" type="..."&gt;
&lt;property name="targetName"&gt;
&lt;idref object="theTargetObject"/&gt;
&lt;/property&gt;
&lt;/object&gt;</programlisting>This above object definition snipped is
<emphasis>exactly</emphasis> equivalent (at runtime) to the
following snippit:<programlisting language="myxml">&lt;object id="theTargetObject" type="..."&gt;
. . .
&lt;/object&gt;
&lt;object id="theClientObject" type="..."&gt;
&lt;property name="targetName" value="theTargetObject"/&gt;
&lt;/object&gt;</programlisting>The first form is preferable to the second is
that using the <literal>idref</literal> tag allows the container to
validate <emphasis>at deployment time</emphasis> that the
referenced, named object actually exists. In the second variation,
no validation is performed on the value that is passed to the
<literal>targetName</literal> property of the client object. Typos
are only discovered (with ost mikely fatal results) when the
'client' object is actually instantiated. If the 'client' object is
a prototype object, this typo and the resulting exception may only
be discovered long after the container is deployed.</para>
<para>Additionally, if the reference object is in the same XML unit,
and the object name is the object <emphasis>id</emphasis>, you can
use the <literal>local</literal> attribute which allows the XML
parser itself to validate the object name earlier, at XML document
parse time. <programlisting language="myxml">&lt;property name="targetName"&gt;
&lt;idref local="theTargetObject"/&gt;
&lt;/property&gt;</programlisting></para>
</sect4>
<sect4>
<title>Whitespace Handling</title>
<para>Usually all leading and trailing whitespaces are trimmed from
a &lt;value /&gt; 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">&lt;property name="myProp"&gt;
&lt;value xml:space="preserve"&gt; &amp;#x000a;&amp;#x000d;&amp;#x0009;&lt;/value&gt;
&lt;/property&gt;</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>References to other objects (collaborators)</title>
<para>The <literal>ref</literal> element is the final element allowed
inside a <literal>&lt;constructor-arg/&gt; or
&lt;property/&gt;</literal> definition element. Here you set the value
of the specified property to be a reference to another object (a
collaborator) managed by the container. The referenced object is a
dependency of the object whose property will be set, and it is
initialzed on demand as needed before the property is set. (If the
collaborator is a singleton object it may be initialized already by
the container.) All references are ultimately just a reference to
another object. Scoping and validation depend on whether you specify
the id/name of the object through the <literal>object</literal>,
<literal>local</literal>, or <literal>parent</literal>
attributes.</para>
<para>Specifying the target object through the
<literal>object</literal> attribute of the <literal>ref</literal> tag
is the most general form, and allows creation of a reference to any
object in the same container or parent container, regardless of
whether it is in the same XML file. The value of the
<literal>object</literal> attribute may be the same as the
<literal>id</literal> attribute of the target object, or as one of the
values in the <literal>name</literal> attribute of the target
object.<programlisting language="myxml">&lt;ref object="someObject"/&gt;</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">&lt;ref local="someObject"/&gt;</programlisting></para>
<para>Specifying the target object through the
<literal>parent</literal> attribute creates a reference to an object
that is in a parent container of the current container. 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 must be in a parent container to the
current one. You use this object reference variant mainly when you
have a hierarchy of containers and you want to wrap an existing object
in a parent container with some sort of proxy which will have the same
name as the parent object.<programlisting language="myxml">&lt;!-- in the parent context --&gt;
&lt;object id="AccountService" type="MyApp.SimpleAccountService, MyApp"&gt;
&lt;!-- insert dependencies as required as here --&gt;
&lt;/object&gt;</programlisting><programlisting language="myxml">&lt;!-- in the child (descendant) context --&gt;
&lt;object id="AccountService" &lt;-- notice that the name of this object is the same as the name of the 'parent' object
type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop"&gt;
&lt;property name="target"&gt;
&lt;ref parent="AccountService"/&gt; &lt;-- notice how we refer to the parent object --&gt;
&lt;/property&gt;
&lt;!-- insert other configuration and dependencies as required as here --&gt;
&lt;/object&gt;</programlisting></para>
</sect3>
<sect3 xml:id="objects-inline-object">
<title>Inner objects</title>
<para>An <literal>&lt;object/&gt;</literal> element inside the
&lt;<literal>constructor-arg/&gt; or &lt;property/&gt;</literal>
element defines so called inner object.</para>
<para><programlisting language="myxml">&lt;object id="outer" type="..."&gt;
&lt;!-- Instead of using a reference to target, just use an inner object --&gt;
&lt;property name="target"&gt;
&lt;object type="ExampleApp.Person, ExampleApp"&gt;
&lt;property name="name" value="Tony"/&gt;
&lt;property name="age" value="51"/&gt;
&lt;/object&gt;
&lt;/property&gt;
&lt;/object&gt;</programlisting></para>
<para>An inner object definition does not require a defined id or
name; the container ignores these values. It also ignores the
<literal>scope</literal> flag. Inner object are
<emphasis>always</emphasis> anonymous and they are
<emphasis>always</emphasis> scoped as prototypes. It is not possible
to inject inner objects into collaborating objects other than into the
enclosing object.</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">&lt;objects xmlns="http://www.springframework.net"&gt;
&lt;object id="moreComplexObject" type="Example.ComplexObject"&gt;
&lt;!--
results in a call to the setter of the SomeList (System.Collections.IList) property
--&gt;
&lt;property name="SomeList"&gt;
&lt;list&gt;
&lt;value&gt;a list element followed by a reference&lt;/value&gt;
&lt;ref object="myConnection"/&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;!--
results in a call to the setter of the SomeDictionary (System.Collections.IDictionary) property
--&gt;
&lt;property name="SomeDictionary"&gt;
&lt;dictionary&gt;
&lt;entry key="a string =&gt; string entry" value="just some string"/&gt;
&lt;entry key-ref="myKeyObject" value-ref="myConnection"/&gt;
&lt;/dictionary&gt;
&lt;/property&gt;
&lt;!--
results in a call to the setter of the SomeNameValue (System.Collections.NameValueCollection) property
--&gt;
&lt;property name="SomeNameValue"&gt;
&lt;name-values&gt;
&lt;add key="HarryPotter" value="The magic property"/&gt;
&lt;add key="JerrySeinfeld" value="The funny (to Americans) property"/&gt;
&lt;/name-values&gt;
&lt;/property&gt;
&lt;!--
results in a call to the setter of the SomeSet (Spring.Collections.ISet) property
--&gt;
&lt;property name="someSet"&gt;
&lt;set&gt;
&lt;value&gt;just some string&lt;/value&gt;
&lt;ref object="myConnection"/&gt;
&lt;/set&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;/objects&gt;</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>The value of a Dictionary entry, or a set value, can
also again be any of the following 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&lt;T&gt;</literal> and <literal>IDictionary&lt;TKey,
TValue&gt;</literal>. The type parameter for these collections is
specified by using the XML attribute <literal>element-type</literal>
for <literal>IList&lt;T&gt;</literal> and the XML attributes
<literal>key-type</literal> and <literal>value-type</literal> for
<literal>IDictionary&lt;TKey, TValue&gt;</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&lt;T&gt;</literal>
and <literal>IDictionary&lt;TKey, TValue&gt;</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&lt;int&gt; list;
DateTime date;
public List&lt;int&gt; 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">&lt;object id="MyLotteryTicket" type="GenericsPlay.Lottery.LotteryTicket, GenericsPlay"&gt;
&lt;property name="Numbers"&gt;
&lt;list element-type="int"&gt;
&lt;value&gt;11&lt;/value&gt;
&lt;value&gt;21&lt;/value&gt;
&lt;value&gt;23&lt;/value&gt;
&lt;value&gt;34&lt;/value&gt;
&lt;value&gt;36&lt;/value&gt;
&lt;value&gt;38&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;property name="Date" value="4/16/2006"/&gt;
&lt;/object&gt;</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&lt;IExpression&gt; expressionsList;
private System.Collections.Generic.IDictionary&lt;string,IExpression&gt; expressionsDictionary;
public System.Collections.Generic.IList&lt;IExpression&gt; ExpressionsList
{
set { this.expressionsList = value; }
}
public System.Collections.Generic.IDictionary&lt;string, IExpression&gt; 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">&lt;object id="genericExpressionHolder"
type="Spring.Objects.Factory.Xml.GenericExpressionHolder,
Spring.Core.Tests"&gt;
&lt;property name="ExpressionsList"&gt;
&lt;list element-type="Spring.Expressions.IExpression, Spring.Core"&gt;
&lt;value&gt;1 + 1&lt;/value&gt;
&lt;value&gt;date('1856-7-9').Month&lt;/value&gt;
&lt;value&gt;'Nikola Tesla'.ToUpper()&lt;/value&gt;
&lt;value&gt;DateTime.Today &gt; date('1856-7-9')&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;property name="ExpressionsDictionary"&gt;
&lt;dictionary key-type="string" value-type="Spring.Expressions.IExpression, Spring.Core"&gt;
&lt;entry key="zero"&gt;
&lt;value&gt;1 + 1&lt;/value&gt;
&lt;/entry&gt;
&lt;entry key="one"&gt;
&lt;value&gt;date('1856-7-9').Month&lt;/value&gt;
&lt;/entry&gt;
&lt;entry key="two"&gt;
&lt;value&gt;'Nikola Tesla'.ToUpper()&lt;/value&gt;
&lt;/entry&gt;
&lt;entry key="three"&gt;
&lt;value&gt;DateTime.Today &gt; date('1856-7-9')&lt;/value&gt;
&lt;/entry&gt;
&lt;/dictionary&gt;
&lt;/property&gt;
&lt;/object&gt;</programlisting></para>
</sect3>
<sect3>
<title>Collection Merging</title>
<para>As of Spring 1.3, the container supports the merging of
collections. An application developer can define a parent-style
<literal>&lt;list/&gt;</literal>,
<literal>&lt;dictionary/&gt;</literal>,
<literal>&lt;set/&gt;</literal> or
<literal>&lt;name-value/&gt;</literal> element, and have child-style
<literal>&lt;list/&gt;</literal>,
<literal>&lt;dictionary/&gt;</literal>,
<literal>&lt;set/&gt;</literal> or
<literal>&lt;name-value/&gt;</literal> elements inherit and override
values from the parent collection. That is, the child collection's
values are the result of merging the elements of the parent and child
collections, with the child's collection elements overriding values
specified in the parent collection.</para>
<para><emphasis>This section on merging discusses the parent-child
object mechanism. Readers unfamiliar with parent and child object
definitions may wish to read the <link
linkend="objects-childobjects">relevant section</link> before
continuing.</emphasis></para>
<para>The following example demonstrates collection merging:</para>
<programlisting language="myxml">&lt;object id="parent" abstract="true" type="Example.ComplexObject, Examples"&gt;
&lt;property name="AdminEmails"&gt;
&lt;name-values&gt;
&lt;add key="administrator" value="administrator@example.com"/&gt;
&lt;add key="support" value="support@example.com"/&gt;
&lt;/name-values&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;object id="child" parent="parent" &gt;
&lt;property name="AdminEmails"&gt;
&lt;!-- the merge is specified on the *child* collection definition --&gt;
&lt;name-values merge="true"&gt;
&lt;add key="sales" value="sales@example.com"/&gt;
&lt;add key="support" value="support@example.co.uk"/&gt;
&lt;/name-values&gt;
&lt;/property&gt;
&lt;/object&gt;</programlisting>
<para>Notice the use of the <literal>merge=true</literal> attribute on
the <literal>&lt;name-values/&gt;</literal> element of the
<literal>AdminEmails</literal> property of the child object
definition. When the child object is resolved and instantiated by the
container, the resulting instance has an
<literal>AdminEmails</literal> Properties collection that contains the
result of the merging of the child's <literal>AdminEmails</literal>
collection with the parent's <literal>AdminEmails</literal>
collection:</para>
<programlisting>administrator=administrator@example.com // from parent
sales=sales@example.com // from child
support=support@example.co.uk // overriden by child</programlisting>
<para>The child Properties collection's value set inherits all
property elements from the parent
<literal>&lt;name-values/&gt;</literal>, and the child's value for the
support value overrides the value in the parent collection. This
merging behavior applies similarly to the
<literal>&lt;list/&gt;</literal>,
<literal>&lt;dictionary/&gt;</literal>, and
<literal>&lt;set/&gt;</literal> collection types. In the specific case
of the <literal>&lt;list/&gt;</literal> element, the semantics
associated with the <literal>IList</literal> collection type, that is,
the notion of an ordered collection of values, is maintained; the
parent's values precede all of the child list's values. In the case of
the <literal>IDictionary</literal>, <literal>ISet</literal>, and
<literal>NameValue</literal> collection types, no ordering exists.
Hence no ordering semantics are in effect for the collection types
that underlie the associated <literal>IDictionary</literal>,
<literal>ISet</literal>, and <literal>NameValueCollection</literal>
implementation types that the container uses internally.</para>
</sect3>
<sect3 xml:id="objects-null-values">
<title>Null and empty values</title>
<para>Spring treats empty arguments for properties and the like as
empty Strings. The following XML-based configuration metadata snippet
sets the email property to the empty String value ("")</para>
<programlisting>&lt;object type="Examples.ExampleObject, ExamplesLibrary"&gt;
&lt;property name="email" value=""/&gt;
&lt;/object&gt;</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</para>
<programlisting language="csharp">exampleObject.Email = "";</programlisting>
<para>The <literal>&lt;null&gt;</literal> element is used to handle
<literal>null</literal> values. For example:</para>
<programlisting language="myxml">&lt;object type="Examples.ExampleObject, ExamplesLibrary"&gt;
&lt;property name="email"&gt;&lt;null/&gt;&lt;/property&gt;
&lt;/object&gt;</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">&lt;object id="person" type="Test.Objects.Person, Test.Objects"&gt;
&lt;property name="[0]" value="Master Shake"/&gt;
&lt;property name="['one']" value="uno"/&gt;
&lt;/object&gt;</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">&lt;object id="objectWithIndexer" type="Spring.Objects.TestObject, Spring.Core.Tests"&gt;
&lt;property name="Item[0]" value="my string value"/&gt;
&lt;/object&gt;</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>Spring XML used to be even more verbose. What is now popular
usage is actually the shortcut from of the original way to specify
values and references.</para>
<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">&lt;property name="myProperty"&gt;
&lt;value&gt;hello&lt;/value&gt;
&lt;/property&gt;
&lt;constructor-arg&gt;
&lt;value&gt;hello&lt;/value&gt;
&lt;/constructor-arg&gt;
&lt;entry key="myKey"&gt;
&lt;value&gt;hello&lt;/value&gt;
&lt;/entry&gt;</programlisting> are equivalent to:<programlisting
language="myxml">&lt;property name="myProperty" value="hello"/&gt;
&lt;constructor-arg value="hello"/&gt;
&lt;entry key="myKey" value="hello"/&gt;</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">&lt;property name="myProperty"&gt;
&lt;ref object="anotherObject"/&gt;
&lt;/property&gt;
&lt;constructor-arg index="0"&gt;
&lt;ref object="anotherObject"/&gt;
&lt;/constructor-arg&gt;</programlisting> is equivalent to... <programlisting
language="myxml">&lt;property name="myProperty" ref="anotherObject"/&gt;
&lt;constructor-arg index="0" ref="anotherObject"/&gt;</programlisting></para>
<note>
<para>The shortcut form is equivalent to a <literal>&lt;ref
object="xxx"&gt;</literal> element; there is no shortcut for either
the <literal>&lt;ref local="xxx"&gt;</literal> or <literal>&lt;ref
parent="xxx"&gt;</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">&lt;entry&gt;
&lt;key&gt;
&lt;ref object="MyKeyObject"/&gt;
&lt;/key&gt;
&lt;ref object="MyValueObject"/&gt;
&lt;/entry&gt;</programlisting> Is equivalent to: <programlisting
language="myxml">&lt;entry key-ref="MyKeyObject" value-ref="MyValueObject"/&gt;</programlisting>
As mentioned previously, the equivalence is to <literal>&lt;ref
object="xxx"&gt;</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>You can use compound or nested property names when you set
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">&lt;object id="foo" type="Spring.Foo, Spring.Foo"&gt;
&lt;property name="bar.baz.name" value="Bingo"/&gt;
&lt;/object&gt;</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>&lt;dictionary&gt;</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">&lt;property name=“minValue” expression=“int.MinValue” /&gt;
&lt;property name=“weekFromToday” expression="DateTime.Today + 7"/&gt;</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>&lt;listener&gt;</literal> element inside your
<literal>&lt;object&gt;</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>&lt;listener&gt;</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>&lt;listener&gt;</literal>
element.</para>
<para><programlisting language="myxml">&lt;object id="eventListener1" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;!-- wired up to an event exposed on an instance --&gt;
&lt;listener event="Click" method="HandleEvent"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;
&lt;object id="eventListener2" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;!-- wired up to an event exposed on an instance --&gt;
&lt;listener event="Click" method="HandleEvent"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;</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">&lt;object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;listener method="Handle.+"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;</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">&lt;object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;!-- For the Click event, the HandleClick handler method will be invoked. --&gt;
&lt;listener method="Handle${event}"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;</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">&lt;object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;listener method="HandleEvent" event="Cl.+"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;</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>If an object is a dependency of another that usually means that
one object is set as a property of another. Typically you accomplish
this with the <literal>&lt;ref/&gt;</literal> element in XML-based
configuration metadata. However, sometimes dependencies between objects
are less direct; for example, a static initializer in a class needs to
be triggered, such as device driver registration. The
<literal>depends-on</literal> attribute can explicitly force one or more
objects to be initialized before the object using this element is
initialized. The following example uses the
<literal>depends-on</literal> attribute to express a dependency on a
single object: <programlisting language="myxml">&lt;object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager"&gt;
&lt;property name="manager" ref="manager"/&gt;
&lt;/object&gt;
&lt;object id="manager" type="Examples.ManagerObject, ExamplesLibrary"/&gt;</programlisting></para>
<para>To express a dependency on multiple objects, supply a list of
object names as the value of the '<literal>depends-on</literal>'
attribute, with commas, whitespace and semicolons used as valid
delimiters:</para>
<programlisting language="myxml">&lt;object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager,accountDao"&gt;
&lt;property name="manager" ref="manager" /&gt;
&lt;/object&gt;
&lt;object id="manager" type="Examples.ManagerObject, ExamplesLibrary" /&gt;
&lt;object id="accountDao" type="Examples.AdoAccountDao, ExamplesLibrary" /&gt;</programlisting>
<note>
<para>The <literal>depends-on</literal> attribute in the object
definition can specify both an initialization time dependency and, in
the case of a singleton object only, a corresponding destroy time
dependency. Dependent objects that define a
<literal>depends-on</literal> relationship with a given object are
destroyed first, prior to the given object itself being destroyed.
Thus <literal>depends-on</literal> can also control shutdown
order.</para>
</note>
</sect2>
<sect2>
<title>Lazily-initialized objects</title>
<para>By default, <literal>IApplicationContext</literal> implementations
eagerly pre-instantiate all singleton objects as part of the
initialization process. Generally this pre-instantiation is desirable,
because errors in configuration or the surrounding environment are
discovered immediately, as opposed to hours or even days later. When
this behavior is not desirable, you can prevent pre-instantiation of a
singleton object by marking the object definition as lazy-initialized. A
lazy-initialized object tells the IoC container to create an object
instance when it is first requested, rather than at startup.</para>
<para>In XML, this behavior is controlled by the
<literal>'lazy-init'</literal>attribute on the
<literal>&lt;object/&gt;</literal> element; for example:</para>
<programlisting language="myxml">&lt;object id="lazy" type="MyCompany.ExpensiveToCreateObject, MyApp" lazy-init="true"/&gt;
&lt;object name="not.lazy" type="MyCompany.AnotherObject, MyApp"/&gt;</programlisting>
<para>When the preceding configuration is consumed by an
<literal>IApplicationContext</literal>, the object named
<literal>lazy</literal> is not eagerly pre-instantiated when the
<literal>IApplicationContext</literal> is starting up, whereas the
<literal>not.lazy</literal> object is eagerly pre-instantiated.</para>
<para>However, when a lazy-initialized object is a dependency of a
singleton object that is <emphasis>not</emphasis>
<literal>lazy-initialized</literal>, the
<classname>IApplicationContext</classname> creates the lazy-initialized
object at startup, because it must satisfy the singleton's dependencies.
The lazy-initialized object is injected into a singleton object
elsewhere that is not lazy-initialized.</para>
<para>You can also control lazy-initialization at the container level by
using the <literal>default-lazy-init </literal>attribute on the
<literal>&lt;objects/&gt;</literal> element; for example:</para>
<programlisting language="myxml">&lt;objects default-lazy-init="true"&gt;
&lt;!-- no objects will be pre-instantiated... --&gt;
&lt;/objects&gt;</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 &lt;object/&gt; 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>The Spring IoC container can check for unresolved dependencies of
an object deployed into the container. When enabling checking for
unresolved dependencies all properties of the object must have an
explicit values set for them in the object definition or have their
values set via autowiring.</para>
<para>This feature useful when you want to ensure that all properties
(or all properties of a certain type) are set on an object. An object
often has default values for many properties, or some properties do not
apply to all usage scenarios, so this feature is of limited use. You can
enable dependency checking per object, just as with the autowiring
functionality. The default is not <emphasis>not</emphasis> check
dependencies. In XML-based configuration metadata, you specify
dependency checking 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>(Default) 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 for primitive types and collections
(everything except collaborators).</entry>
</row>
<row>
<entry>object</entry>
<entry>Dependency checking for collaborators only.</entry>
</row>
<row>
<entry>all</entry>
<entry>Dependency checking for collaborators, primitive types
and collections.</entry>
</row>
</tbody>
</tgroup>
</table></para>
</sect2>
<sect2 xml:id="objects-method-injection">
<title>Method injection</title>
<para>In most application scenarios, most object in the container are
singletons. When a singleton object needs to collaborate with another
singleton object, or a non-singleton object needs to collaborate with
another non-singleton object, you typically handle the dependency by
defining one object as a property of the other. A problem arrises when
the object lifecycles are different. Suppose singleton object A needs to
use a non-singleton (prototype) object B, perhaps on each method
invocation on A. The container only creates the singleton object A once,
and thus only gets one opportunity to set the properties. The container
cannot provide object A with a new instance of object B every time one
is needed.</para>
<para>A solution is to forego some inversion of control. You can <link
linkend="objects-factory-aware-objectfactoryaware">make object A aware
of the container</link> by implementing the
<literal>IApplicationContextAware</literal> interface, and by <link
linkend="objects-factory-client">making a GetObject("B") call to the
container</link> ask for (a typically new) object B every time it needs
it. Find below an 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 preceding is not desirable, because the business code is aware
of and coupled to the Sring 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 is the ability of the container to
override methods on <emphasis>container managed objects</emphasis>, to
return the result of looking up another named object in the container.
The lookup typically involves a prototype object as in the scenario
described in the preceding section. 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.</para>
<note>
<para>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>
</note>
<para>Looking at the <literal>CommandManager</literal> class in the
previous code snippit, you see that the Spring container will
dynamically override the implementation of the
<literal>CreateCommand()</literal> method. Your
<literal>CommandManager</literal> class will not 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
<classname>CommandManager</classname> in this case) the method to be
injected requires a signature of the following form:</para>
<programlisting language="myxml">&lt;public|protected&gt; [abstract] &lt;return-type&gt; TheMethodName(no-arguments);</programlisting>
<para>If the method is <literal>abstract</literal>, the
dynamically-generated subclass implements the method. Otherwise, the
dynamically-generated subclass overrides the concrete method defined
in the original class. Let's look at an example:</para>
<programlisting language="myxml">&lt;!-- a stateful object deployed as a prototype (non-singleton) --&gt;
&lt;object id="command" class="Fiona.Apple.AsyncCommand, Fiona" singleton="false"&gt;
&lt;!-- inject dependencies here as required --&gt;
&lt;/object&gt;
&lt;!-- commandProcessor uses a statefulCommandHelpder --&gt;
&lt;object id="commandManager" type="Fiona.Apple.CommandManager, Fiona"&gt;
&lt;lookup-method name="CreateCommand" object="command"/&gt;
&lt;/object&gt;</programlisting>
<para>The object identified as <literal>commandManager</literal> will
calls its own method <literal>CreateCommand</literal> whenever it
needs a new instance of the <literal>command</literal> object. You
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.</para>
<para>With XML-based configuration metadata, you can use the
<literal>replaced-method</literal> element to replace an existing
method implementation with another, for a deployed object. 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">/// &lt;summary&gt;
/// Meant to be used to override the existing ComputeValue(string)
/// implementation in MyValueCalculator.
/// &lt;/summary&gt;
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">&lt;object id="myValueCalculator" type="Examples.MyValueCalculator, ExampleAssembly"&gt;
&lt;!-- arbitrary method replacement --&gt;
&lt;replaced-method name="ComputeValue" replacer="replacementComputeValue"&gt;
&lt;arg-type match="String"/&gt;
&lt;/replaced-method&gt;
&lt;/object&gt;
&lt;object id="replacementComputeValue" type="Examples.ReplacementComputeValue, ExampleAssembly"/&gt;</programlisting>
<para>You can use one or more contained <literal>arg-type</literal>
elements within the <literal>replaced-method</literal> element to
indicate the method signature of the method being overridden. The
signature for the arguments is necessaryonly if the method is
overloaded and multiple variants exist within the class. For
convenience, the type string for an argument may be a substring of the
fully qualified type name. For example, the following all match
<literal>System.String</literal>.</para>
<programlisting language="csharp"> System.String
String
Str</programlisting>
<para>Because the number of arguments is often enough to distinguish
between each possible choice, this shortcut can save a lot of typing,
by allowing you to typ just the shortest string which will match an
argument type.</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">&lt;object name="person" type="Spring.Objects.TestObject, Spring.Core.Tests"&gt;
&lt;property name="age" value="20"/&gt;
&lt;property name="spouse"&gt;
&lt;object type="Spring.Objects.TestObject, Spring.Core.Tests"&gt;
&lt;property name="age" value="21"/&gt;
&lt;/object&gt;
&lt;/property&gt;
&lt;/object&gt;
// will result in 21, which is the value of property 'spouse.age' of object 'person'
&lt;object name="theAge" type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core"&gt;
&lt;property name="TargetObject" ref="person"/&gt;
&lt;property name="TargetProperty" value="spouse.age"/&gt;
&lt;/object&gt;</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">&lt;object id="cultureAware"
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"&gt;
&lt;property name="culture" ref="cultureFactory"/&gt;
&lt;/object&gt;
&lt;object id="cultureFactory"
type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core"&gt;
&lt;property name="StaticProperty"&gt;
&lt;value&gt;System.Globalization.CultureInfo.CurrentUICulture, Mscorlib&lt;/value&gt;
&lt;/property&gt;
&lt;/object&gt;</programlisting>
<para>Similarly, an example showing the use of an instance property is
shown below.</para>
<programlisting language="myxml">&lt;object id="instancePropertyCultureAware"
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"&gt;
&lt;property name="Culture" ref="instancePropertyCultureFactory"/&gt;
&lt;/object&gt;
&lt;object id="instancePropertyCultureFactory"
type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core"&gt;
&lt;property name="TargetObject" ref="instancePropertyCultureAwareSource"/&gt;
&lt;property name="TargetProperty" value="MyDefaultCulture"/&gt;
&lt;/object&gt;
&lt;object id="instancePropertyCultureAwareSource"
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/&gt;
</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">&lt;object id="withTypesField"
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"&gt;
&lt;property name="Types" ref="emptyTypesFactory"/&gt;
&lt;/object&gt;
&lt;object id="emptyTypesFactory"
type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core"&gt;
&lt;property name="TargetType" value="System.Type, Mscorlib"/&gt;
&lt;property name="TargetField" value="EmPTytypeS"/&gt;
&lt;/object&gt;
</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">&lt;object id="instanceCultureAware"
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"&gt;
&lt;property name="Culture" ref="instanceCultureFactory"/&gt;
&lt;/object&gt;
&lt;object id="instanceCultureFactory"
type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core"&gt;
&lt;property name="TargetObject" ref="instanceCultureAwareSource"/&gt;
&lt;property name="TargetField" value="Default"/&gt;
&lt;/object&gt;
&lt;object id="instanceCultureAwareSource"
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/&gt;
</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">&lt;object id="force-init"
type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"&gt;
&lt;property name="StaticMethod"&gt;
&lt;value&gt;ExampleNamespace.ExampleInitializerClass.Initialize&lt;/value&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;object id="myService" depends-on="force-init"/&gt;</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">&lt;object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"&gt;
&lt;property name="TargetType" value="Whatever.MyClassFactory, MyAssembly"/&gt;
&lt;property name="TargetMethod" value="GetInstance"/&gt;
&lt;!-- the ordering of arguments is significant --&gt;
&lt;property name="Arguments"&gt;
&lt;list&gt;
&lt;value&gt;1st&lt;/value&gt;
&lt;value&gt;2nd&lt;/value&gt;
&lt;value&gt;and 3rd arguments&lt;/value&gt;
&lt;!-- automatic Type-conversion will be performed prior to invoking the method --&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/object&gt;</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">&lt;object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"&gt;
&lt;property name="TargetObject"&gt;
&lt;object type="Whatever.MyClassFactory, MyAssembly"/&gt;
&lt;/property&gt;
&lt;property name="TargetMethod" value="Execute"/&gt;
&lt;!-- the ordering of named arguments is not significant --&gt;
&lt;property name="NamedArguments"&gt;
&lt;dictionary&gt;
&lt;entry key="argumentName"&gt;&lt;value&gt;1st&lt;/value&gt;&lt;/entry&gt;
&lt;entry key="finalArgumentName"&gt;&lt;value&gt;and 3rd arguments&lt;/value&gt;&lt;/entry&gt;
&lt;entry key="anotherArgumentName"&gt;&lt;value&gt;2nd&lt;/value&gt;&lt;/entry&gt;
&lt;/dictionary&gt;
&lt;/property&gt;
&lt;/object&gt;</programlisting></para>
<para>The following example shows how use
<literal>MethodInvokingFactoryObject</literal> to call an instance
method.<programlisting language="myxml">&lt;object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" /&gt;
&lt;object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"&gt;
&lt;property name="TargetObject" ref="myMethodObject"/&gt;
&lt;property name="TargetMethod" value="Execute"/&gt;
&lt;/object&gt;</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">&lt;object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" /&gt;
&lt;object id="paramsMethodObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"&gt;
&lt;property name="TargetObject" ref="myMethodObject"/&gt;
&lt;property name="TargetMethod" value="CreateObject"/&gt;
&lt;property name="Arguments"&gt;
&lt;list&gt;
&lt;value&gt;System.String&lt;/value&gt;
&lt;!-- here is the 'params string[] arguments' --&gt;
&lt;list&gt;
&lt;value&gt;1st&lt;/value&gt;
&lt;value&gt;2nd&lt;/value&gt;
&lt;/list&gt;
&lt;/list&gt;
&lt;/object&gt;</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">&lt;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" &gt;
&lt;object name="daoLogger" type="Spring.Objects.Factory.Config.LogFactoryObject, Spring.Core"&gt;
&lt;property name="logName" value="DAOLogger"/&gt;
&lt;/object&gt;
&lt;object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp "&gt;
&lt;property name="maxResults" value="100"/&gt;
&lt;property name="dbConnection" ref="myConnection"/&gt;
&lt;property name="log" ref="daoLogger"/&gt;
&lt;/object&gt;
&lt;object name="accountDao" type="PropPlayApp.SimpleAccountDao, PropPlayApp "&gt;
&lt;property name="maxResults" value="100"/&gt;
&lt;property name="dbConnection" ref="myConnection"/&gt;
&lt;property name="log" ref="daoLogger"/&gt;
&lt;/object&gt;
&lt;object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data"&gt;
&lt;property name="connectionstring" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/&gt;
&lt;/object&gt;
&lt;/objects&gt;</programlisting></para>
</sect3>
</sect2>
</sect1>
<sect1 xml:id="objects-factory-scopes">
<title>Object Scopes</title>
<para>When you create an object definition, you create a
<emphasis>recipe</emphasis> for creating actual instances of the class
defined by that object definition. The idea that an object definition is a
recipe is important, because it means that, as with a class, you can
create many object instances 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 <emphasis>scope</emphasis> of
the objects created from a particular object definition. This approach
powerful and flexible in that you can <emphasis>choose</emphasis> 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. Ob jects can be
defined to be deployed in one of a number of scopes: out of the box, the
Spring Framework supports five scopes, three of which are available only
if you use a web-aware
<interfacename>IApplicationContext</interfacename>.</para>
<para>The following scopes supported. Support for user defined custom
scopes is planned for Spring .NET 2.0.</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 has 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>Singleton scoped objects have only one shared instance of an
object managed by the container. All request for objects with an id or
ids matching that object definition 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, the Spring IoC container creates exactly one
instance of the object defined by that object definition. This single
instance is stored in a cache of such singleton object, and all
subsequent requests and references for that named object return the
cached object.</para>
<para>Spring's concept of a singleton differns from the Singleton
pattern as defined in the Gang of Four (GoF) patterns book. The GoF
Singleton hard-codes the scope of an object such that one <emphasis>and
only one</emphasis> instance of a particular class is created per
ApplicationDomain. The scope of the Spring singleton is best described
as <emphasis>per container and per object</emphasis>. This means that if
you define one object for a particular class in a single Spring
container, then the Spring container creates one <emphasis>and only
one</emphasis> 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, for example:</para>
<programlisting language="myxml">&lt;object id="accountService" type="MyApp.DefaultAccountService, MyApp"/&gt;
&lt;!-- the following is equivalent, though redundant (singleton scope is the default) --&gt;
&lt;object id="accountService" type="MyApp.DefaultAccountService, MyApp" singleton="true"/&gt;
</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 <emphasis>new object instance</emphasis> every time a
request for that specific object is made. That is, the object is
injected into another object or you request through a
<literal>GetObject()</literal> method call on the container. As a rule
use the prototype scope for all objects that are stateful and the
singleton scope for stateless objects.</para>
<para>The following examples defines an object as a prototype in
XML:</para>
<programlisting language="myxml">&lt;object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary" scope="prototype"/&gt;</programlisting>
<note>
<para>The <literal>&lt;singleton/&gt;</literal> attribute was
introduced Spring 1.0 as there were only two types of scopes,
singleton and prototype. The element singleton=true refers to
singleton scope and singleton=false refers to prototype scope. In
Spring 1.1 the additional web scopes were introduced along with the
new elment 'scope'. The scope element is the preferred element to
use.</para>
</note>
<para>In contrast to the other scopes, 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, with no further record of that prototype instance.
Thus, although <emphasis>initialization</emphasis> lifecycle callback
methods are called on all objects regardless of scope, in the case of
prototypes, configured <emphasis>destruction</emphasis> lifecycle
callbacks are <emphasis>not</emphasis> called. The client code must
clean up prototype-scoped objects and release any expensive resources
that the prototype object(s) are holding. To get the Spring container to
release resources held by prototype-scoped objects, try using a custom
<link linkend="objects-factory-customizing">object post processor</link>
which would hold a reference to the objects that need to be cleaned
up.</para>
<para>In some respects, the Spring container's role in regard to a
prototype-scoped object is a replacement for the C# 'new' operator. All
lifecycle management past that point must be handled by the client. (For
details on the lifecycle of an object in the Spring container, see <xref
linkend="objects-factory-lifecycle" />.</para>
</sect2>
<sect2 xml:id="objects-factory-scopes-sing-prot-interaction">
<title>Singleton objects with prototype-object dependencies</title>
<para>When you use singleton-scoped objects with dependencies on
prototype objects, be aware that <emphasis>dependencies are resolved at
instantiation time</emphasis>. Thus if you dependency-inject a
prototype-scoped objects into a singleton-scoped object, a new prototype
object is instantiated and then dependency-injected into the singleton
object. The prototype instance is the sole instance that is ever
supplied to the singleton-scoped object.</para>
<para>However, suppose you want the singleton-scoped object to acquire a
new instance of the prototype-scoped object repeatedly at runtime. You
cannot dependency-inject a prototype-scoped object into your singleton
object, because that injection occurs only once, when the Spring
container is instantiating the singleton object and resolving and
injecting its dependencies. If you need a new instance of a prototype
object at runtime more than once, see <xref
linkend="objects-method-injection" />.</para>
</sect2>
<sect2>
<title>Request, session and web application scopes</title>
<para>The <link linkend="???">request</link>, <link
linkend="???">session</link> and <link linkend="???">application</link>
scopes are <emphasis>only</emphasis> available if you use a web-aware
Spring <interfacename>IApplicationContext</interfacename>
implementation, such as <classname>WebApplicationContext</classname>. If
you use these scopes with regular Spring IoC containers such as the
<classname>XmlApplicationContext</classname>, you will get an exception
complaining about an unknown object scope.</para>
<para>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">&lt;object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests"&gt;
&lt;property name="name" value="Rod"/&gt;
&lt;property name="FileMode" value="Create"/&gt;
&lt;/object&gt;</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">&lt;object name="sample" type="SimpleApp.DependsOnExoticType, SimpleApp"&gt;
&lt;property name="exoticType" value="aNameForExoticType"/&gt;
&lt;/object&gt;</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">&lt;object id="customConverterConfigurer"
type="Spring.Objects.Factory.Config.CustomConverterConfigurer, Spring.Core"&gt;
&lt;property name="CustomConverters"&gt;
&lt;dictionary&gt;
&lt;entry key="SimpleApp.ExoticType"&gt;
&lt;object type="SimpleApp.ExoticTypeConverter"/&gt;
&lt;/entry&gt;
&lt;/dictionary&gt;
&lt;/property&gt;
&lt;/object&gt;</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>To interact with the container's management of the object
lifecycle, you can implement the Spring
<literal>InitializingObject</literal> and standard
<literal>System.IDisposable</literal> interfaces. The container calls
<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. You
can also achieve the same integration with the container without
coupling your objects to Spring interfaces though the use of
<literal>init-method</literal> and <literal>destroy-method</literal>
object definition metadata.</para>
<para>Internally, Spring.NET uses implementations of the
<literal>IObjectPostProcessor</literal> interface to process any call
interfaces it can find and call the appropriate methods. If you need
custom features or other lifecycle behavior Spring.NET does not offer
out-of-the-box, you can implement an
<literal>IObjectPostProcessor</literal> yourself. For more information
see<xref linkend="objects-factory-customizing" />.</para>
<para></para>
<sect3 xml:id="objects-factory-lifecycle-initializingobject">
<title>IInitializingObject / <literal>init-method</literal></title>
<para>The
<literal>Spring.Objects.Factory.IInitializingObject</literal>
interface allows an object to perform initialization work after all
the necessary properties on an object are set by the container. The
<literal>IInitializingObject</literal> interface specifies a single
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>
<para>It is recommended that you do not use the
<literal>IInitializingObject</literal> interface because it
unnecessarily coupules the code to Spring. Alternatively, specify an
POJO initialization method. In the case of XML-based configuration
metadata, you use the <literal>init-method</literal> attribute to
specify the name of the method that has a void no-argument signature.
For example, the following definition:</para>
<para><programlisting language="myxml">&lt;object id="exampleInitObject" type="Examples.ExampleObject" init-method="init"/&gt;</programlisting></para>
<para><programlisting language="csharp">[C#]
public class ExampleObject
{
public void Init()
{
// do some initialization work
}
}</programlisting></para>
<para>...is exactly the same as...</para>
<para><programlisting language="myxml">&lt;object id="exampleInitObject" type="Examples.AnotherExampleObject"/&gt;</programlisting><programlisting
language="csharp">[C#]
public class AnotherExampleObject : IInitializingObject
{
public void AfterPropertiesSet()
{
// do some initialization work
}
}</programlisting>... but does not couple the code to Spring.NET.</para>
</sect3>
<sect3 xml:id="objects-factory-lifecycle-disposableobject">
<title>IDisposable / <literal>destroy-method</literal></title>
<para>Implementing the <literal>System.IDisposable</literal> interface
allows an object to get a callback callback when the container
containing it is destroyed. The <literal>IDisposable</literal>
interface specifies a single 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.v</para>
</listitem>
</itemizedlist></para>
<para>Since the <classname>IDisposable</classname> interface resides
in the core .NET library, it does not couple your class to Spring as
in the case with the <classname>IInitializingObject</classname>
interface. However, you may also specify a destruction method that is
not tied to the <classname>IDisposable</classname> interface. In the
case of XML-based configuration metadata, you use the
<literal>destroy-method</literal> attribute to specify the name of the
method that has a void no-argument signature. For example, the
following definition:</para>
<para><programlisting language="myxml">&lt;object id="exampleInitObject" type="Examples.AnotherExampleObject" /&gt;</programlisting></para>
<para><programlisting language="csharp">[C#]
public class AnotherExampleObject : IDisposable
{
public void Dispose()
{
// do some destruction work
}
}</programlisting></para>
</sect3>
</sect2>
<sect2 xml:id="objects-factory-aware">
<title>IApplicationContextAware and IObjectNameAware</title>
<para>When an <classname>IApplicationContext</classname> creates a class
that implements the <classname>IApplicationContextAware</classname>
interface, the class is provided with a reference to that
<classname>IApplicationContext</classname>.</para>
<programlisting language="csharp">public interface IApplicationContextAware
{
IApplicationContext ApplicationContext { set; }
}</programlisting>
<para>Thus objects can manipulate programmatically the
<classname>IApplicationContext</classname> that created them, through
the <classname>IApplicationContext</classname> interface, or by casting
the reference to a known subclass of this interface, such as
<classname>IConfigurableApplicationContext</classname>, which exposes
additional functionality. One use would be the programmatic retrieval of
other objects. Sometimes this capability is useful; however, in general
you should avoid it, because it couples the code to Spring and does not
follow the Inversion of Control style, where collaborators are provided
to objects as properties. Other methods of the
<classname>IApplicationContext</classname> provide access to file
resources, publishing application events, and accessing a
<classname>IMessageSource</classname>. These additional features are
described in <xref linkend="context-introduction" /></para>
<sect3 xml:id="objects-factory-aware-objectnameaware">
<title>IObjectNameAware</title>
<para>When an <classname>IApplicationContext</classname> creates a
class that implements the
<literal>Spring.Objects.Factory.IObjectNameAware</literal> interface,
the class is provided with a reference to the name defined in its
associated object definition.</para>
<programlisting language="csharp">public interface IObjectNameAware
{
string ObjectName { set; }
}</programlisting>
<para>The callback is invoked after population of normal object
properties but before an initialization callback such as
<classname>IInitializingObject</classname> 's AfterPropertiesSet
method or a custom initalization method is invoked.</para>
</sect3>
</sect2>
</sect1>
<sect1 xml:id="objects-childobjects">
<title>Object definition inheritance</title>
<para>An object definition can contain a lot of configuration information,
including constructor arguments, property values, and container-specific
information such as initialization method, static factory method name, and
so on. A child object definition inherits configuration data from a parent
definition. The child definition can override some values, or add others,
as needed. Using parent and child object definitions can save a lot of
typing. Effectively, this is a form of templating.</para>
<para>If you work with an IApplicationContext interface programmatically,
child object definitions are represented by the
<literal>ChildObjectDefinition</literal> class. Most users do not work
with them on this level, instead configuring object definitions
declaratively in something like the
<literal>XmlApplicationContext.</literal> When you use XML-based
configuration metadata, you indicate a child object using the parent
attribute, specifying the parent object definition as the value of this
attribute.</para>
<para><programlisting language="myxml">&lt;object id="inheritedTestObject" type="Spring.Objects.TestObject, Spring.Core.Tests" abstract="true"&gt;
&lt;property name="name" value="parent"/&gt;
&lt;property name="age" value="1"/&gt;
&lt;/object&gt;
&lt;object id="inheritsWithDifferentClass" type="Spring.Objects.DerivedTestObject, Spring.Core.Tests"
parent="inheritedTestObject" init-method="Initialize"&gt;
&lt;property name="name" value="override"/&gt;
&lt;!-- age will inherit value of 1 from parent --&gt;
&lt;/object&gt;</programlisting></para>
<para>A child object definition uses 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, that is,
it must accept the parent's property values.</para>
<para>A child object definition inherits constructor argument values,
property values and method overrides from the parent, with the option to
add new values. Any initialization method, destroy method and/or static
factory methods that you specify will override the corresponding parent
settings.</para>
<para>The remaining settings are 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>The preceding example explicitly marks the parent object definition
as abstract using the <literal>abstract</literal> attribute. If the parent
definition does not specify a class, explicitly marking the parent object
definition as abstract is required, as follows:<programlisting
language="myxml">&lt;object id="inheritedTestObjectWithoutClass" abstract="true"&gt;
&lt;property name="name" value="parent"/&gt;
&lt;property name="age" value="1"/&gt;
&lt;/object&gt;
&lt;object id="inheritsWithClass" type="Spring.Objects.DerivedTestObject, Spring.Core.Tests"
parent="inheritedTestObjectWithoutClass" init-method="Initialize"&gt;
&lt;property name="name" value="override"/&gt;
&lt;!-- age will inherit value of 1 from parent --&gt;
&lt;/object&gt;</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 abstract like this, it is usable only as a pure template
object definition that serves 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, returns an
error. The container's internal
<methodname>PreInstantiateSingletons</methodname> method will completely
ignore object definitions that are considered abstract.</para>
<note>
<para>Application contexts pre-instantiate all singletons by default.
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>Container extension points</title>
<para>The Spring container is essentially nothing more than an advanced
factory capable of maintaining a registry of different</para>
<para>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">&lt;object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/&gt;
&lt;object id="anotherObject" type="Examples.ExampleObject, ExamplesLibrary" singleton="false"/&gt;</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, string
name):</literal> Injects dependencies into the supplied target
instance assigning the supplied name to the abstract object
definition. 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>
</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>&amp;</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("&amp;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">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;objects xmlns="http://www.springframework.net" &gt;
&lt;description&gt;An example that demonstrates simple IoC features.&lt;/description&gt;
&lt;object id="MyMovieLister"
type="Spring.IocQuickStart.MovieFinder.MovieLister, Spring.IocQuickStart.MovieFinder"&gt;
&lt;property name="movieFinder" ref="MyMovieFinder"/&gt;
&lt;/object&gt;
&lt;object id="MyMovieFinder"
type="Spring.IocQuickStart.MovieFinder.SimpleMovieFinder, Spring.IocQuickStart.MovieFinder"/&gt;
&lt;!-- when the above objects are instantiated, this custom IObjectPostProcessor implementation
will output the fact to the system console --&gt;
&lt;object type="Spring.IocQuickStart.MovieFinder.TracingObjectPostProcessor, Spring.IocQuickStart.MovieFinder"/&gt;
&lt;/objects&gt;</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">&lt;object id="MyMovieLister"
type="Spring.IocQuickStart.MovieFinder.MovieLister, Spring.IocQuickStart.MovieFinder"&gt;
&lt;!-- whoops, no MovieFinder is set (and this property is [Required]) --&gt;
&lt;/object&gt;</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">&lt;object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"/&gt;</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">&lt;object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"&gt;
&lt;property name="RequiredAttributeType" value="MyApp.Attributes.MandatoryAttribute, MyApp"/&gt;
&lt;/object&gt;</programlisting>
</sect3>
</sect2>
<sect2 xml:id="objects-factory-customizing-factory-postprocessors">
<title>Customizing configuration metadata with
<literal>IObjectFactoryPostProcessors</literal></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 <literal>IObjectFactory</literal>) or automatically (in the case of
an <literal>IApplicationContext</literal>) 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
&lt;objects/&gt; 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 <literal>${variableName}</literal>, and obtain their
values from <literal>NameValueSections</literal> in the standard .NET
application configuration file. The Spring.NET configuration file
looks like: <programlisting language="myxml">&lt;configuration&gt;
&lt;configSections&gt;
&lt;sectionGroup name="spring"&gt;
&lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&gt;
&lt;/sectionGroup&gt;
&lt;section name="DaoConfiguration" type="System.Configuration.NameValueSectionHandler"/&gt;
&lt;section name="DatabaseConfiguration" type="System.Configuration.NameValueSectionHandler"/&gt;
&lt;/configSections&gt;
&lt;DaoConfiguration&gt;
&lt;add key="maxResults" value="1000"/&gt;
&lt;/DaoConfiguration&gt;
&lt;DatabaseConfiguration&gt;
&lt;add key="connection.string" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/&gt;
&lt;/DatabaseConfiguration&gt;
&lt;spring&gt;
&lt;context&gt;
&lt;resource uri="assembly://DaoApp/DaoApp/objects.xml"/&gt;
&lt;/context&gt;
&lt;/spring&gt;
&lt;/configuration&gt;</programlisting></para>
<para>Notice the presence of two <literal>NameValueSection</literal>s
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">&lt;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" &gt;
&lt;object name="productDao" type="DaoApp.SimpleProductDao, DaoApp "&gt;
&lt;property name="maxResults" value="${maxResults}"/&gt;
&lt;property name="dbConnection" ref="myConnection"/&gt;
&lt;/object&gt;
&lt;object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data"&gt;
&lt;property name="connectionstring" value="${connection.string}"/&gt;
&lt;/object&gt;
&lt;object name="appConfigPropertyHolder"
type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core"&gt;
&lt;property name="configSections"&gt;
&lt;value&gt;DaoConfiguration,DatabaseConfiguration&lt;/value&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;/objects&gt;</programlisting>
<para>The values of <literal>${maxResults}</literal> and
<literal>${connection.string}</literal> match the key names used in
the two <literal>NameValueSectionHandler</literal>s
<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">&lt;section name="hibernateConfiguration"
type="System.Configuration.NameValueFileSectionHandler, System,
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/&gt;</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">&lt;object id="MyMovieFinder" type="${custom.moviefinder.type}"/&gt;</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
<literal>PreInstantiateSingletons()</literal> phase of an
<literal>ApplicationContext</literal> for a non-lazy-init
object.)</para>
<para>Similarly you can replace 'ref' and 'expression' metadata, as
shown below</para>
<programlisting language="myxml">&lt;object id="TestObject" type="Simple.TestObject, MyAssembly"&gt;
&lt;property name="age" expression="${ageExpression}"/&gt;
&lt;property name="spouse" ref="${spouse-ref}"/&gt;
&lt;/object&gt;</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">&lt;object name="appConfigPropertyHolder"
type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core"&gt;
&lt;property name="configSections" value="DaoConfiguration,DatabaseConfiguration"/&gt;
&lt;property name="EnvironmentVariableMode" value="Override"/&gt;
&lt;/object&gt;
&lt;/objects&gt;</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">&lt;configuration&gt;
&lt;configSections&gt;
&lt;sectionGroup name="spring"&gt;
&lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&gt;
&lt;/sectionGroup&gt;
&lt;section name="DaoConfigurationOverride" type="System.Configuration.NameValueSectionHandler"/&gt;
&lt;/configSections&gt;
&lt;DaoConfigurationOverride&gt;
&lt;add key="productDao.maxResults" value="1000"/&gt;
&lt;/DaoConfigurationOverride&gt;
&lt;spring&gt;
&lt;context&gt;
&lt;resource uri="assembly://DaoApp/DaoApp/objects.xml"/&gt;
&lt;/context&gt;
&lt;/spring&gt;
&lt;/configuration&gt;</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">&lt;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" &gt;
&lt;object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp " &gt;
&lt;property name="maxResults" value="2000"/&gt;
&lt;property name="dbConnection" ref="myConnection"/&gt;
&lt;property name="log" ref="daoLog"/&gt;
&lt;/object&gt;
&lt;object name="daoLog" type="Spring.Objects.Factory.Config.LogFactoryObject, Spring.Core"&gt;
&lt;property name="logName" value="DAOLogger"/&gt;
&lt;/object&gt;
&lt;object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data"&gt;
&lt;property name="connectionstring"&gt;
&lt;value&gt;dsn=MyDSN;uid=sa;pwd=myPassword;&lt;/value&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;object name="appConfigPropertyOverride" type="Spring.Objects.Factory.Config.PropertyOverrideConfigurer, Spring.Core"&gt;
&lt;property name="configSections"&gt;
&lt;value&gt;DaoConfigurationOverride&lt;/value&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;/objects&gt;</programlisting></para>
</sect3>
<sect3 xml:id="objects-variablesource">
<title>Example: The
<literal>VariablePlaceholderConfigurer</literal></title>
<para>The <literal>VariablePlaceholderConfigurer</literal> is an
evolution of the <literal>PropertyPlaceHolderConfigurer</literal>. 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, the registry and the new connection strings configuration
section in .NET 2.0. It is possible to add your own variable sources
to a <literal>VariablePlaceholderConfigurer</literal> by implementing
the <literal>IVariableSource</literal> interface.</para>
<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">&lt;object type="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core"&gt;
&lt;property name="VariableSources"&gt;
&lt;list&gt;
&lt;object type="Spring.Objects.Factory.Config.PropertyFileVariableSource, Spring.Core"&gt;
&lt;property name="Location" value="~\application.properties" /&gt;
&lt;/object&gt;
&lt;object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core"&gt;
&lt;property name="SectionNames" value="CryptedConfiguration" /&gt;
&lt;/object&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/object&gt; </programlisting></para>
<para>The variable sources that Spring.NET provides out of the box are
described in the following sections.</para>
<sect4>
<title><literal>ConfigSectionVariableSource</literal></title>
<para>The <literal>ConfigSectionVariableSource</literal> allows you
to define variables in a custom configuration section in your
configuration file:</para>
<programlisting language="myxml">&lt;!-- app.config: --&gt;
&lt;configuration&gt;
&lt;configSections&gt;
&lt;section name="DonConfiguration" type="System.Configuration.NameValueSectionHandler"/&gt;
&lt;/configSections&gt;
&lt;DonConfiguration&gt;
&lt;add key="don_name" value="Dick Whitman"/&gt;
&lt;add key="don_age" value="41" /&gt;
&lt;/DonConfiguration&gt;
&lt;/configuration&gt;
&lt;!-- VariableSource configuration: --&gt;
&lt;object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core"&gt;
&lt;property name="SectionNames" value="DonConfiguration" /&gt;
&lt;/object&gt;
&lt;!-- consume variables: --&gt;
&lt;object type="Example.Person, Spring.IocQuickStart.VariableSources"&gt;
&lt;property name="Name" value="${don_name}" /&gt;
&lt;property name="Age" value="${don_age}" /&gt;
&lt;/object&gt;
</programlisting>
<para>This is similar to using the
<literal>PropertyPlaceHolderConfigurer</literal> described
above.</para>
<para>By simply configuring the appropriate section, you can use the
<literal>ConfigSectionVariableSource</literal> to retrieve variables
from .NET's application settings and user settings. Assuming your
application's root namespace is <literal>MyApp</literal>, then your
application- and user settings can be loaded as variables by
configuring the following variable sources:</para>
<programlisting language="myxml">&lt;!-- From .net's ApplicationSettings: --&gt;
&lt;object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core"&gt;
&lt;property name="SectionNames" value="applicationSettings/MyApp.Properties.Settings" /&gt;
&lt;/object&gt;
&lt;!-- From .net's UserSettings: --&gt;
&lt;object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core"&gt;
&lt;property name="SectionNames" value="userSettings/MyApp.Properties.Settings" /&gt;
&lt;/object&gt;
</programlisting>
<para>If you configured your application settings as such:</para>
<para><mediaobject>
<imageobject>
<imagedata fileref="images/applicationsettings.png"></imagedata>
</imageobject>
</mediaobject>Then you can use <literal>${peggy_name}</literal>,
<literal>${peggy_age}</literal>,
<literal>&amp;{peter_name}</literal> and
<literal>${peter_age}</literal> as variables in your object
definitions. They will be retrieved using the appropriate
scope.<note>
<para>Changes to user settings during the lifetime of your
application context will <emphasis>not</emphasis> be be visible
to the <literal>ConfigSectionVariableSource</literal>. Although
variables based on user settings will be resolved using user
scope, variables will <emphasis>only be resolved when the
<literal>VariablePlaceholderConfigurer</literal> is
initialized</emphasis>: that is when the context is created. Any
object (including lazy-loaded singletons and non-singletons) you
retrieve from the context will have the variable values injected
as they were when the context was loaded.</para>
</note></para>
</sect4>
<sect4>
<title><literal>PropertyFileVariableSource</literal></title>
<para>A <literal>PropertyFileVariableSource</literal> allows to read
properties defined in a Java-style property file as variables.
Assume a file named <literal>application.properties</literal> in
your application folder containing the following lines:</para>
<programlisting>joan_name=Joan Harris
joan_age=35</programlisting>
<para>You can use the <literal>${joan_name}</literal> and
<literal>${joan_age}</literal> variables in your object definitions
if you configure the following variable source:</para>
<para><programlisting>&lt;object type="Spring.Objects.Factory.Config.PropertyFileVariableSource, Spring.Core"&gt;
&lt;property name="Location" value="~\application.properties" /&gt;
&lt;property name="IgnoreMissingResources" value="true"/&gt;
&lt;/object&gt;</programlisting></para>
<para><note>
<para>The use of the <property>IgnoreMissingResources</property>
property above will mean that if the property file is not found
it will be silently ignored and the resolution will continue to
the next variable source(s) of the
<literal>VariablePlaceholderConfigurer</literal>.</para>
</note></para>
</sect4>
<sect4>
<title><literal>ConfigurableVariableSource</literal></title>
<para>A <literal>ConfigurableVariableSource</literal> allows you
define variables inline in a variable source definition. To
configure the variables <literal>${midge_name}</literal> and
<literal>${midge_age}</literal>, you can use the following
<literal>ConfigurableVariableSource</literal> definition:</para>
<programlisting language="myxml">&lt;object type="Spring.Objects.Factory.Config.ConfigurableVariableSource, Spring.Core"&gt;
&lt;property name="Variables"&gt;
&lt;name-values&gt;
&lt;add key="midge_name" value="Midge Daniels"/&gt;
&lt;add key="midge_age" value="33"/&gt;
&lt;/name-values&gt;
&lt;/property&gt;
&lt;/object&gt;</programlisting>
</sect4>
<sect4>
<title><literal>CommandLineArgsVariableSource</literal></title>
<para>You can use commandline arguments as a source for variables.
Assume you issue the following command to start your application
<literal>myapp</literal>:</para>
<para><programlisting>myapp /roger_name:"Roger Sterling" /roger_age:57</programlisting></para>
<para>The following variable source configuration allows you to use
<literal>${roger_name}</literal> and <literal>${roger_age}</literal>
as variables:</para>
<programlisting language="myxml">&lt;object type="Spring.Objects.Factory.Config.CommandLineArgsVariableSource, Spring.Core"&gt;
&lt;property name="ArgumentPrefix" value ="/" /&gt; &lt;!-- optional; default: "/" --&gt;
&lt;property name="ValueSeparator" value=":" /&gt; &lt;!-- optional; default: ":" --&gt;
&lt;/object&gt;</programlisting>
</sect4>
<sect4>
<title><literal>RegistryVariableSource</literal></title>
<para>Entries in the Windows registry can be used as variables. When
your registry contains the key
<literal>HKEY_CURRENT_USER\MyKey</literal> with entries
<literal>freddy_name</literal> and <literal>freddy_age</literal>,
then you can configure the following variable source to use
<literal>${freddy_name}</literal> and
<literal>${freddy_age}</literal> as variables:</para>
<programlisting language="myxml">&lt;object type="Spring.Objects.Factory.Config.RegistryVariableSource, Spring.Core"&gt;
&lt;property name="Key" value="HKEY_CURRENT_USER\MyKey" /&gt;
&lt;/object&gt;</programlisting>
</sect4>
<sect4>
<title><literal>EnvironmentVariableSource</literal></title>
<para>You can configure an
<literal>EnvironmentVariableSource</literal> to retrieve variables
from environment variables available through <link
ns6:href="http://msdn.microsoft.com/en-us/library/system.environment.aspx">.NET's
<literal>System.Environment</literal> class</link>:</para>
<programlisting language="myxml">&lt;object type="Spring.Objects.Factory.Config.EnvironmentVariableSource, Spring.Core" /&gt;
</programlisting>
<para>To resolve a variable named <literal>${ken_name}</literal>,
the <literal>EnvironmentVariableSource</literal> will directly call
<literal>System.Environment.GetEnvironmentVariable("ken_name")</literal>.</para>
</sect4>
<sect4>
<title><literal>ConnectionStringsVariableSource</literal></title>
<para>Visual Studio has support for configuring database connection
strings in a <literal>connectionStrings</literal> section in your
application configuration file. You can retrieve these connections
as variables by configuring a
<literal>ConnectionStringsVariableSource</literal>:</para>
<programlisting language="myxml">&lt;object type="Spring.Objects.Factory.Config.ConnectionStringsVariableSource, Spring.Core" /&gt;</programlisting>
<para>Assuming the following connection strings section in your
application configuration file:</para>
<programlisting language="myxml">&lt;connectionStrings&gt;
&lt;add name="myConnection"
connectionString="Data Source=myserver;Integrated Security=True;..."
providerName="System.Data.SqlClient" /&gt;
&lt;/connectionStrings&gt;</programlisting>
<para>Then you would use the variables as in following object
definition:</para>
<programlisting language="myxml">&lt;object type="Example.MyClass, MyAssembly"&gt;
&lt;property name="ConnectionString" value="${myConnection.connectionString}" /&gt;
&lt;property name="ProviderName" value="${myConnection.providerName}" /&gt;
&lt;/object&gt; </programlisting>
<para><note>
<para>Append ".connectionString" to the connection name to get
the connection string and append ".providerName" to the
connection name to get the provider name.</para>
</note><note>
<para>When adding a connection using Visual Studio's application
settings user interface, your connection will be named similar
to <literal>MyApp.Properties.Settings.myConnection</literal> and
the corresponding variable name for the connection string would
become
<literal>MyApp.Properties.Settings.myConnection.connectionString</literal>.</para>
</note></para>
</sect4>
<sect4>
<title><literal>SpecialFolderVariableSource</literal></title>
<para>The <literal>SpecialFolderVariableSource</literal> resolves
the full path for variable names against special folders as defined
by the <literal>System.Environment.SpecialFolder</literal>
enumeration. Add it to your variable sources as:</para>
<para><programlisting language="myxml">&lt;object type="Spring.Objects.Factory.Config.SpecialFolderVariableSource, Spring.Core" /&gt;</programlisting></para>
<para>Now you can inject the full path to the current user's
desktop, or to this machine's program files folders:</para>
<programlisting language="myxml">&lt;object id="specials" type="Example.Specials, Spring.IocQuickStart.VariableSources"&gt;
&lt;property name="FullPathToDesktop" value="${Desktop}" /&gt;
&lt;property name="FullPathToPrgramFiles" value="${ProgramFiles}" /&gt;
&lt;/object&gt;</programlisting>
<para>Any entry in the <link
ns6:href="http://msdn.microsoft.com/library/system.environment.specialfolder.aspx">System.Environment.SpecialFolder</link>
enumeration can be used as a variable name.</para>
</sect4>
<sect4>
<title>Custom <literal>IVariableSource</literal>
implementations</title>
<para>The <literal>IVariableSource</literal> is the base interface
for providing the ability to get the value of property placeholders
(name-value) pairs from a variety of sources. The
<literal>IVariableSource</literal> interface is shown below:</para>
<programlisting language="csharp">public interface IVariableSource
{
bool CanResolveVariable(string name);
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
<literal>VariablePlaceholderConfigurer</literal> to refer to your
class.</para>
</sect4>
</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>&amp;</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("&amp;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">&lt;configuration&gt;
&lt;configSections&gt;
&lt;sectionGroup name="spring"&gt;
&lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&gt;
&lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /&gt;
&lt;section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/&gt;
&lt;section name="resourceHandlers" type="Spring.Context.Support.ResourceHandlersSectionHandler, Spring.Core"/&gt;
&lt;section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/&gt;
&lt;section name="typeConverters" type="Spring.Context.Support.TypeConvertersSectionHandler, Spring.Core"/&gt;
&lt;/sectionGroup&gt;
&lt;/configSections&gt;
&lt;spring&gt;
&lt;parsers&gt;
&lt;parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" /&gt;
&lt;parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /&gt;
&lt;/parsers&gt;
&lt;resourceHandlers&gt;
&lt;handler protocol="db" type="MyCompany.MyApp.Resources.MyDbResource"/&gt;
&lt;/resourceHandlers&gt;
&lt;context caseSensitive="false"&gt;
&lt;resource uri="config://spring/objects"/&gt;
&lt;resource uri="db://user:pass@dbName/MyDefinitionsTable"/&gt;
&lt;/context&gt;
&lt;typeAliases&gt;
&lt;alias name="WebServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web"/&gt;
&lt;alias name="DefaultPointcutAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/&gt;
&lt;alias name="AttributePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop"/&gt;
&lt;alias name="CacheAttribute" type="Spring.Attributes.CacheAttribute, Spring.Core"/&gt;
&lt;alias name="MyType" type="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/&gt;
&lt;/typeAliases&gt;
&lt;typeConverters&gt;
&lt;converter for="Spring.Expressions.IExpression, Spring.Core" type="Spring.Objects.TypeConverters.ExpressionConverter, Spring.Core"/&gt;
&lt;converter for="MyTypeAlias" type="MyCompany.MyProject.Converters.MyTypeConverter, MyAssembly"/&gt;
&lt;/typeConverters&gt;
&lt;objects xmlns="http://www.springframework.net"&gt;
...
&lt;/objects&gt;
&lt;/spring&gt;
&lt;/configuration&gt;
</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 &lt;parser&gt; 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">&lt;configuration&gt;
&lt;configSections&gt;
&lt;sectionGroup name="spring"&gt;
&lt;!-- other configuration section handler defined here --&gt;
&lt;section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/&gt;
&lt;/sectionGroup&gt;
&lt;/configSections&gt;
&lt;spring&gt;
&lt;parsers&gt;
&lt;parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" /&gt;
&lt;parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /&gt;
&lt;parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" /&gt;
&lt;parser type="Spring.Validation.Config.ValidationNamespaceParser, Spring.Core" /&gt;
&lt;parser type="Spring.Remoting.Config.RemotingNamespaceParser, Spring.Services" /&gt;
&lt;/parsers&gt;
&lt;/spring&gt;
&lt;/configuration&gt;</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">&lt;object id="myResourceHandlers" type="Spring.Objects.Factory.Config.ResourceHandlerConfigurer, Spring.Core"&gt;
&lt;property name="ResourceHandlers"&gt;
&lt;dictionary&gt;
&lt;entry key="db" value="MyCompany.MyApp.Resources.MyDbResource, MyAssembly"/&gt;
&lt;/dictionary&gt;
&lt;/property&gt;
&lt;/object&gt;</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">&lt;object id="MyWebService" type="WebServiceExporter"&gt;
...
&lt;/object&gt;
&lt;object id="cacheAspect" type="DefaultPointcutAdvisor"&gt;
&lt;property name="Pointcut"&gt;
&lt;object type="AttributePointcut"&gt;
&lt;property name="Attribute" value="CacheAttribute"/&gt;
&lt;/object&gt;
&lt;/property&gt;
&lt;property name="Advice" ref="aspNetCacheAdvice"/&gt;
&lt;/object&gt;</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 &lt;alias&gt; elements each with a name and
a type attribute. Below is an example that registers the alias for
WebServiceExporter</para>
<programlisting language="myxml">&lt;configuration&gt;
&lt;configSections&gt;
&lt;sectionGroup name="spring"&gt;
&lt;!-- other configuration section handler defined here --&gt;
&lt;section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/&gt;
&lt;/sectionGroup&gt;
&lt;/configSections&gt;
&lt;spring&gt;
&lt;typeAliases&gt;
&lt;alias name="WebServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web"/&gt;
&lt;/typeAliases&gt;
&lt;/spring&gt;
&lt;/configuration&gt;</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 &lt;objects&gt; 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">&lt;object id="myTypeAlias" type="Spring.Objects.Factory.Config.TypeAliasConfigurer, Spring.Core"&gt;
&lt;property name="TypeAliases"&gt;
&lt;dictionary&gt;
&lt;entry key="WebServiceExporter" value="Spring.Web.Services.WebServiceExporter, Spring.Web"/&gt;
&lt;entry key="DefaultPointcutAdvisor" value="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/&gt;
&lt;entry key="MyType" value="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/&gt;
&lt;/dictionary&gt;
&lt;/property&gt;
&lt;/object&gt;</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">&lt;object id="myTypeConverters" type="Spring.Objects.Factory.Config.CustomConverterConfigurer, Spring.Core"&gt;
&lt;property name="CustomConverters"&gt;
&lt;dictionary&gt;
&lt;entry key="System.Date" value="MyCompany.MyProject.MyNamespace.MyCustomDateConverter, MyAssembly"/&gt;
&lt;/dictionary&gt;
&lt;/property&gt;
&lt;/object&gt;</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">&lt;spring&gt;
&lt;context&gt;
&lt;resource uri="assembly://MyAssembly/MyProject/root-objects.xml"/&gt;
&lt;context name="mySubContext"&gt;
&lt;resource uri="file://objects.xml"/&gt;
&lt;/context&gt;
&lt;/context&gt;
&lt;/spring&gt;</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>&lt;objects&gt;</literal> as the root name. Another example of
a hierarchy, but using sections in the application configuration file is
shown below. <programlisting language="myxml">&lt;configSections&gt;
&lt;sectionGroup name="spring"&gt;
&lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&gt;
&lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /&gt;
&lt;sectionGroup name="child"&gt;
&lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /&gt;
&lt;/sectionGroup&gt;
&lt;/sectionGroup&gt;
&lt;/configSections&gt;
&lt;spring&gt;
&lt;context name="ParentContext"&gt;
&lt;resource uri="config://spring/objects"/&gt;
&lt;context name="ChildContext"&gt;
&lt;resource uri="config://spring/child/objects"/&gt;
&lt;/context&gt;
&lt;/context&gt;
&lt;objects xmlns="http://www.springframework.net"&gt;
...
&lt;/objects&gt;
&lt;child&gt;
&lt;objects xmlns="http://www.springframework.net"&gt;
...
&lt;/objects&gt;
&lt;/child&gt;
&lt;/spring&gt;</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">&lt;object name="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core"&gt;
&lt;property name="resourceManagers"&gt;
&lt;list&gt;
&lt;value&gt;Spring.Examples.AppContext.MyResource, Spring.Examples.AppContext&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/object&gt;</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">&lt;object name="myResourceManager" type="Spring.Objects.Factory.Config.ResourceManagerFactoryObject, Spring.Core"&gt;
&lt;property name="baseName"&gt;
&lt;value&gt;Spring.Examples.AppContext.MyResource&lt;/value&gt;
&lt;/property&gt;
&lt;property name="assemblyName"&gt;
&lt;value&gt;Spring.Examples.AppContext&lt;/value&gt;
&lt;/property&gt;
&lt;/object&gt;</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>IApplicationEventListener</literal>
interface that contains the single method <literal>void
HandleApplicationEvent( object source, ApplicationEventArgs
applicationEventArgs )</literal>. Classes that implement the
<literal>IApplicationEventListener</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">&lt;object id="emailer" type="Example.EmailObject"&gt;
&lt;property name="blackList"&gt;
&lt;list&gt;
&lt;value&gt;black@list.org&lt;/value&gt;
&lt;value&gt;white@list.org&lt;/value&gt;
&lt;value&gt;john@doe.org&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;object id="blackListListener" type="Example.BlackListNotifier"&gt;
&lt;property name="notificationAddress"&gt;
&lt;value&gt;spam@list.org&lt;/value&gt;
&lt;/property&gt;
&lt;/object&gt;</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 : IApplicationEventListener
{
// notification address
private string notificationAddress;
public string NotificationAddress
{
set { this.notificationAddress = value; }
}
public void HandleApplicationEvent(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">&lt;spring&gt;
&lt;context&gt;
&lt;resource uri="assembly://MyAssembly/MyProject/root-objects.xml"/&gt;
&lt;context name="mySubContext"&gt;
&lt;resource uri="file://objects.xml"/&gt;
&lt;/context&gt;
&lt;/context&gt;
&lt;/spring&gt;</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>