6478 lines
309 KiB
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><object/></literal>
|
|
elements inside a top-level <objects/> 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"><objects xmlns="http://www.springframework.net">
|
|
|
|
<object id="..." type="...">
|
|
<!-- collaborators and configuration for this object go here -->
|
|
</object>
|
|
|
|
<object id="...." type="...">
|
|
<!-- collaborators and configuration for this object go here -->
|
|
</object>
|
|
|
|
<!-- more object definitions go here -->
|
|
|
|
</objects></programlisting>
|
|
|
|
<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"><objects xmlns="http://www.springframework.net">
|
|
|
|
<object id="PetStore" type="PetStore.Services.PetStoreService, PetStore">
|
|
<property name="AccountDao" ref="AccountDao"/>
|
|
<property name="ItemDao" ref="ItemDao"/>
|
|
<!-- additional collaborators and configuration for this object go here -->
|
|
</object>
|
|
|
|
<!-- more object definitions for services go here -->
|
|
|
|
</objects></programlisting>The following example shows the data access
|
|
objects <literal>(daos.xml)</literal> configuration file:</para>
|
|
|
|
<programlisting language="myxml"><objects xmlns="http://www.springframework.net">
|
|
|
|
<object id="AccountDao" type="Petstore.Dao.HibernateAccountDao, PetStore">
|
|
<!-- additional collaborators and configuration for this object go here -->
|
|
</object>
|
|
|
|
<object id="ItemDao" type="Petstore.Dao.HibernateItemDao, PetStore">
|
|
<!-- additional collaborators and configuration for this object go here -->
|
|
</object>
|
|
|
|
<!-- more object definitions for data access objects go here -->
|
|
</objects></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://<AssemblyName>/<NameSpace>/<ResourceName></literal>.
|
|
The <literal>IResource</literal> abstraction is explained further in
|
|
<xref linkend="objects-iresource" />.</para>
|
|
|
|
<note>
|
|
<para>To create an embedded resource using Visual Studio you must
|
|
set the Build Action of the .xml configuration file to Embedded
|
|
Resource in the file property editor. Also, you will need to
|
|
explicitly rebuild the project containing the configuration file if
|
|
it is the only change you make between successive builds. If using
|
|
NAnt to build, add a <resources> section to the csc task. For
|
|
example usage, look at the Spring.Core.Tests.build file included the
|
|
distribution.</para>
|
|
</note>
|
|
</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"><spring>
|
|
<context>
|
|
<resource uri="file://services.xml"/>
|
|
<resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/>
|
|
</context>
|
|
</spring> </programlisting>The context type (specified as the value of
|
|
the <literal>type</literal> attribute of the
|
|
<literal>context</literal> element) is 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"><spring>
|
|
<context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
|
|
<resource uri="file:///services.xml"/>
|
|
<resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/>
|
|
</context>
|
|
</spring></programlisting></para>
|
|
|
|
<para>To acquire a reference to an
|
|
<literal>IApplicationContext</literal> using a custom configuration
|
|
section, one simply uses the following code; <programlisting
|
|
language="csharp">IApplicationContext ctx = ContextRegistry.GetContext();</programlisting>
|
|
The <literal>ContextRegistry</literal> is used to both instantiate the
|
|
application context and to perform service locator style access to
|
|
other objects. (See <xref linkend="objects-servicelocator" /> for more
|
|
information). The glue that makes this possible is an implementation
|
|
of the Base Class Library (BCL) provided
|
|
<literal>IConfigurationSectionHandler</literal> interface, namely the
|
|
<literal>Spring.Context.Support.ContextHandler</literal> class. The
|
|
handler class needs to be registered in the
|
|
<literal>configSections</literal> section of the .NET configuration
|
|
file as shown below. <programlisting language="myxml"><configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
</configSections> </programlisting>This declaration now enables the use
|
|
of a custom context section starting at the <literal>spring</literal>
|
|
root element.</para>
|
|
|
|
<para>In some usage scenarios, user code will not have to explicitly
|
|
instantiate an appropriate implementation
|
|
<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"><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
|
|
<context>
|
|
<resource uri="config://spring/objects"/>
|
|
</context>
|
|
|
|
<objects xmlns="http://www.springframework.net">
|
|
...
|
|
</objects>
|
|
|
|
</spring>
|
|
|
|
</configuration></programlisting></para>
|
|
|
|
<para>Other options available to structure the configuration files are
|
|
described in <xref linkend="context-functionality-hierarchy" /> and
|
|
<xref linkend="objects-factory-xml-import" />.</para>
|
|
|
|
<para>The <literal>IApplicationContext</literal> can be configured to
|
|
register other resource handlers, custom parsers to integrate
|
|
user-contributed XML schema into the object definitions section, type
|
|
converters, and define type aliases. These features are discussed in
|
|
section <xref linkend="context-configuration" /></para>
|
|
</sect3>
|
|
|
|
<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><import/></literal>
|
|
element to load object definitions from another file (or files). For
|
|
example:</para>
|
|
|
|
<para><programlisting language="myxml"><objects xmlns="http://www.springframework.net">
|
|
|
|
<import resource="services.xml"/>
|
|
<import resource="resources/messageSource.xml"/>
|
|
<import resource="/resources/themeSource.xml"/>
|
|
|
|
<object id="object1" type="..."/>
|
|
<object id="object2" type="..."/>
|
|
|
|
</objects></programlisting></para>
|
|
|
|
<para>In 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><objects/></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
|
|
<alias/> element to accomplish this.</para>
|
|
|
|
<programlisting language="myxml"> <alias name="fromName" alias="toName"/></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"><alias name="SubsystemA-DbProvider" alias="SubsystemB-DbProvider"/>
|
|
<alias name="SubsystemA-DbProvider" alias="MyApp-DbProvider"/></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><object/></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"><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/></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"><object id="exampleObject" type="Examples.ExampleObject+Person, ExamplesLibrary"/></programlisting></para>
|
|
|
|
<para>If you are defining classes that have been compiled into
|
|
assemblies that are available to your application (such as the
|
|
<literal>bin</literal> directory in the case of ASP.NET applications)
|
|
via the standard assembly probing mechanisms, then you can specify
|
|
simply the name of the assembly (e.g.
|
|
<literal>ExamplesLibrary.Data</literal>)... this way, when (or if) the
|
|
assemblies used by your application are updated, you won't have to
|
|
change the value of every <literal><object/></literal>
|
|
definition's <literal>type</literal> attribute to reflect the new
|
|
version number (if the version number has changed)... Spring.NET will
|
|
automatically locate and use the newer versions of your assemblies
|
|
(and their attendant classes) from that point forward.</para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-factory-class-static-factory-method">
|
|
<title>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"><object id="exampleObject"
|
|
type="Examples.ExampleObjectFactory, ExamplesLibrary"
|
|
factory-method="CreateInstance"/></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"><!-- the factory object, which contains an instance method called 'CreateInstance' -->
|
|
<object id="exampleFactory" type="...">
|
|
<!-- inject any dependencies required by this object -->
|
|
</object>
|
|
|
|
<!-- the object that is to be created by the factory object -->
|
|
<object id="exampleObject"
|
|
factory-method="CreateInstance"
|
|
factory-object="exampleFactory"/></programlisting></para>
|
|
|
|
<para>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<T>
|
|
{
|
|
private List<T> list;
|
|
|
|
private String name;
|
|
|
|
public List<T> Contents
|
|
{
|
|
get { return list; }
|
|
set { list = value; }
|
|
}
|
|
|
|
public String Name
|
|
{
|
|
get { return name; }
|
|
set { name = value; }
|
|
}
|
|
|
|
public List<T> ApplyFilter(string filterExpression)
|
|
{
|
|
/// should really apply filter to list ;)
|
|
return new List<T>();
|
|
}
|
|
|
|
}
|
|
}</programlisting> The XML configuration to create and configure this object
|
|
is shown below <programlisting language="myxml"><object id="myFilteredIntList" type="GenericsPlay.FilterableList&lt;int>, GenericsPlay">
|
|
<property name="Name" value="My Integer List"/>
|
|
</object></programlisting> There are a few items to note in terms how to
|
|
specify a generic type. First, the left bracket that specifies the
|
|
generic type, i.e. <literal><</literal>, is replaced with the
|
|
string &lt; due to XML escape syntax for the less than symbol.
|
|
Yes, we all realize this is less than ideal from the readability point
|
|
of view. Second, the generic type arguments can not be fully assembly
|
|
qualified as the comma is used to separate generic type arguments.
|
|
Alternative characters used to overcome the two quirks can be
|
|
implemented in the future but so far, all proposals don't seem to help
|
|
clarify the text. The suggested solution to improve readability is to
|
|
use type aliases as shown below <programlisting language="myxml"><typeAliases>
|
|
<alias name="GenericDictionary" type=" System.Collections.Generic.Dictionary&lt;,>" />
|
|
<alias name="myDictionary" type="System.Collections.Generic.Dictionary&lt;int,string>" />
|
|
</typeAliases>
|
|
</programlisting> So that instead of something like this <programlisting
|
|
language="myxml"><object id="myGenericObject"
|
|
type="GenericsPlay.ExampleGenericObject&lt;System.Collections.Generic.Dictionary&lt;int , string>>, GenericsPlay" /></programlisting>
|
|
It can be shortened to <programlisting language="myxml"><object id="myOtherGenericObject"
|
|
type="GenericsPlay.ExampleGenericObject&lt;GenericDictionary&lt;int , string>>, GenericsPlay" /></programlisting>
|
|
or even shorter <programlisting language="myxml"><object id="myOtherOtherGenericObject"
|
|
type="GenericsPlay.ExampleGenericObject&lt;MyIntStringDictionary>, GenericsPlay" />
|
|
</programlisting> Refer to <xref linkend="context-configuration" /> for
|
|
additional information on using type aliases.</para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-factory-generic-static-factory">
|
|
<title>Object creation of generic types via static factory
|
|
method</title>
|
|
|
|
<para>The following classes are used to demonstrate the ability to
|
|
create instances of generic types that themselves are created via a
|
|
static generic factory method. <programlisting language="csharp">public class TestGenericObject<T, U>
|
|
{
|
|
public TestGenericObject()
|
|
{
|
|
}
|
|
|
|
private IList<T> someGenericList = new List<T>();
|
|
|
|
private IDictionary<string, U> someStringKeyedDictionary =
|
|
new Dictionary<string, U>();
|
|
|
|
public IList<T> SomeGenericList
|
|
{
|
|
get { return someGenericList; }
|
|
set { someGenericList = value; }
|
|
}
|
|
|
|
public IDictionary<string, U> SomeStringKeyedDictionary
|
|
{
|
|
get { return someStringKeyedDictionary; }
|
|
set { someStringKeyedDictionary = value; }
|
|
}
|
|
|
|
}</programlisting> The accompanying factory class is <programlisting
|
|
language="csharp">
|
|
public class TestGenericObjectFactory
|
|
{
|
|
public static TestGenericObject<V, W> StaticCreateInstance<V, W>()
|
|
{
|
|
return new TestGenericObject<V, W>();
|
|
}
|
|
|
|
public TestGenericObject<V, W> CreateInstance<V, W>()
|
|
{
|
|
return new TestGenericObject<V, W>();
|
|
}
|
|
}
|
|
</programlisting> The XML snippet to create an instance of TestGenericObject
|
|
where <literal>V</literal> is a List of integers and
|
|
<literal>W</literal> is an integer is shown below <programlisting
|
|
language="myxml"><object id="myTestGenericObject"
|
|
type="GenericsPlay.TestGenericObjectFactory, GenericsPlay"
|
|
factory-method="StaticCreateInstance&lt;System.Collections.Generic.List&lt;int>,int>"
|
|
/></programlisting> The StaticCreateInstance method is responsible for
|
|
instantiating the object that will be associated with the id
|
|
'myTestGenericObject'.</para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-factory-generic-instance-factory">
|
|
<title>Object creation of generic types via instance factory
|
|
method</title>
|
|
|
|
<para>Using the class from the previous example the XML snippet to
|
|
create an instance of a generic type via an instance factory method is
|
|
shown below <programlisting language="myxml"><object id="exampleFactory" type="GenericsPlay.TestGenericObject&lt;int,string>, GenericsPlay"/>
|
|
|
|
<object id="anotherTestGenericObject"
|
|
factory-object="exampleFactory"
|
|
factory-method="CreateInstance&lt;System.Collections.Generic.List&lt;int>,int>"/>
|
|
</programlisting> This creates an instance of
|
|
<literal>TestGenericObject<List<int>,int></literal></para>
|
|
</sect3>
|
|
</sect2>
|
|
</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><contructor-arg/></literal> element.</para>
|
|
|
|
<programlisting language="myxml"><object id="foo" type="X.Y.Foo, Example">
|
|
<constructor-arg ref="bar"/>
|
|
<constructor-arg ref="baz"/>
|
|
</object>
|
|
|
|
<object id="bar" type="X.Y.Bar, Example"/>
|
|
<object id="baz" type="X.Y.Baz, Example"/>
|
|
</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><value>true<value></literal>, Spring cannot
|
|
determine the type of the value, and so cannot match by type without
|
|
help. Consider the following class:</para>
|
|
|
|
<programlisting language="csharp">using System;
|
|
|
|
namespace SimpleApp
|
|
{
|
|
public class ExampleObject
|
|
{
|
|
private int years; //No. of years to the calculate the Ultimate Answer
|
|
|
|
private string ultimateAnswer; //The Answer to Life, the Universe, and Everything
|
|
|
|
public ExampleObject(int years, string ultimateAnswer)
|
|
{
|
|
this.years = years;
|
|
this.ultimateAnswer = ultimateAnswer;
|
|
}
|
|
|
|
}</programlisting>
|
|
|
|
<sect5 xml:id="objects-ctor-arg-type-matching">
|
|
<title>Constructor argument type matching</title>
|
|
|
|
<para>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"><object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
|
|
<constructor-arg type="int" value="7500000"/>
|
|
<constructor-arg type="string" value="42"/>
|
|
</object></programlisting></para>
|
|
|
|
<para>The type attribute specifies the
|
|
<literal>System.Type</literal> of the constructor argument, such
|
|
as System.Int32. Alias' are available to for common simple types
|
|
(and their array equivalents). These alias' are... <table
|
|
frame="all">
|
|
<title>Type aliases</title>
|
|
|
|
<tgroup cols="3">
|
|
<colspec colname="c1" colwidth="1*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<colspec colname="c3" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Type</entry>
|
|
|
|
<entry>Alias'</entry>
|
|
|
|
<entry>Array Alias'</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>System.Char</entry>
|
|
|
|
<entry>char, Char</entry>
|
|
|
|
<entry>char[], Char()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Int16</entry>
|
|
|
|
<entry>short, Short</entry>
|
|
|
|
<entry>short[], Short()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Int32</entry>
|
|
|
|
<entry>int, Integer</entry>
|
|
|
|
<entry>int[], Integer()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Int64</entry>
|
|
|
|
<entry>long, Long</entry>
|
|
|
|
<entry>long[], Long()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.UInt16</entry>
|
|
|
|
<entry>ushort</entry>
|
|
|
|
<entry>ushort[]</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.UInt32</entry>
|
|
|
|
<entry>uint</entry>
|
|
|
|
<entry>uint[]</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.UInt64</entry>
|
|
|
|
<entry>ulong</entry>
|
|
|
|
<entry>ulong[]</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Float</entry>
|
|
|
|
<entry>float, Single</entry>
|
|
|
|
<entry>float[], Single()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Double</entry>
|
|
|
|
<entry>double, Double</entry>
|
|
|
|
<entry>double[], Double()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Date</entry>
|
|
|
|
<entry>date, Date</entry>
|
|
|
|
<entry>date[], Date()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Decimal</entry>
|
|
|
|
<entry>decimal, Decimal</entry>
|
|
|
|
<entry>decimal[], Decimal()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.Bool</entry>
|
|
|
|
<entry>bool, Boolean</entry>
|
|
|
|
<entry>bool[], Boolean()</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>System.String</entry>
|
|
|
|
<entry>string, String</entry>
|
|
|
|
<entry>string[], String()</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
</sect5>
|
|
|
|
<sect5 xml:id="objects-ctor-arg-index">
|
|
<title>Constructor argument Index</title>
|
|
|
|
<para>Use the <literal>index</literal> attribute to specify
|
|
explicitly the index of constructor arguments. For example:</para>
|
|
|
|
<para><programlisting language="myxml"><object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
|
|
<constructor-arg index="0" value="7500000"/>
|
|
<constructor-arg index="1" value="42"/>
|
|
</object></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><constructor-arg></literal> element.</para>
|
|
|
|
<programlisting language="myxml"><object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
|
|
<constructor-arg name="years" value="7500000"/>
|
|
<constructor-arg name="ultimateAnswer" value="42"/>
|
|
</object></programlisting>
|
|
</sect5>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-setter-injection">
|
|
<title>Setter-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"><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary">
|
|
|
|
<!-- setter injection using the ref attribute -->
|
|
<property name="objectOne" ref="anotherExampleObject"/>
|
|
<property name="objectTwo" ref="yetAnotherObject"/>
|
|
<property name="IntegerProperty" value="1"/>
|
|
</object>
|
|
|
|
<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
|
|
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/></programlisting>
|
|
<programlisting language="csharp">[C#]
|
|
public class ExampleObject
|
|
{
|
|
private AnotherObject objectOne;
|
|
private YetAnotherObject objectTwo;
|
|
private int i;
|
|
|
|
public AnotherObject ObjectOne
|
|
{
|
|
set { this.objectOne = value; }
|
|
}
|
|
|
|
public YetAnotherObject ObjectTwo
|
|
{
|
|
set { this.objectTwo = value; }
|
|
}
|
|
|
|
public int IntegerProperty
|
|
{
|
|
set { this.i = value; }
|
|
}
|
|
}</programlisting></para>
|
|
|
|
<para>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"><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary">
|
|
<constructor-arg name="objectOne" ref="anotherExampleObject"/>
|
|
<constructor-arg name="objectTwo" ref="yetAnotherObject"/>
|
|
<constructor-arg name="IntegerProperty" value="1"/>
|
|
</object>
|
|
|
|
<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
|
|
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/></programlisting>
|
|
<programlisting language="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"><object id="exampleObject" type="Examples.ExampleFactoryMethodObject, ExamplesLibrary"
|
|
factory-method="CreateInstance">
|
|
<constructor-arg name="objectOne" ref="anotherExampleObject"/>
|
|
<constructor-arg name="objectTwo" ref="yetAnotherObject"/>
|
|
<constructor-arg name="intProp" value="1"/>
|
|
</object>
|
|
|
|
<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
|
|
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/></programlisting>
|
|
<programlisting language="csharp">[C#]
|
|
public class ExampleFactoryMethodObject
|
|
{
|
|
private AnotherObject objectOne;
|
|
private YetAnotherObject objectTwo;
|
|
private int i;
|
|
|
|
// a private constructor
|
|
private ExampleFactoryMethodObject()
|
|
{
|
|
}
|
|
|
|
public static ExampleFactoryMethodObject CreateInstance(AnotherObject objectOne,
|
|
YetAnotherObject objectTwo,
|
|
int intProp)
|
|
{
|
|
ExampleFactoryMethodObject fmo = new ExampleFactoryMethodObject();
|
|
fmo.AnotherObject = objectOne;
|
|
fmo.YetAnotherObject = objectTwo;
|
|
fmo.IntegerProperty = intProp;
|
|
return fmo;
|
|
}
|
|
|
|
// Property definitions
|
|
|
|
}</programlisting>Arguments to the static factory method are supplied via
|
|
<literal><constructor-arg/></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"><object id="exampleObject" type="Examples.MixedIocObject, ExamplesLibrary">
|
|
<constructor-arg name="objectOne" ref="anotherExampleObject"/>
|
|
<property name="objectTwo" ref="yetAnotherObject"/>
|
|
<property name="IntegerProperty" value="1"/>
|
|
</object>
|
|
|
|
<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
|
|
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/></programlisting>
|
|
<programlisting language="csharp">[C#]
|
|
public class MixedIocObject
|
|
{
|
|
private AnotherObject objectOne;
|
|
private YetAnotherObject objectTwo;
|
|
private int i;
|
|
|
|
public MixedIocObject (AnotherObject obj)
|
|
{
|
|
this.objectOne = obj;
|
|
}
|
|
|
|
public YetAnotherObject ObjectTwo
|
|
{
|
|
set { this.objectTwo = value; }
|
|
}
|
|
|
|
public int IntegerProperty
|
|
{
|
|
set { this.i = value; }
|
|
}
|
|
}</programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="object-factory-properties-detailed">
|
|
<title>Dependencies and configuration in detail</title>
|
|
|
|
<para>As mentioned in the previous section, 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><property/></literal> and
|
|
<<literal>constructor-arg/></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><property/></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"><objects xmlns="http://www.springframework.net">
|
|
<object id="myConnection" type="System.Data.SqlClient.SqlConnection">
|
|
<!-- results in a call to the setter of the ConnectionString property -->
|
|
<property
|
|
name="ConnectionString"
|
|
value="Integrated Security=SSPI;database=northwind;server=mySQLServer"/>
|
|
</object>
|
|
</objects></programlisting></para>
|
|
|
|
<sect4>
|
|
<title>The idref element</title>
|
|
|
|
<para>An idref element is simply an error-proof way to pass the
|
|
<emphasis>id</emphasis> (string value - not a reference) of another
|
|
object in the container to a
|
|
<literal><constructor-arg/></literal> or
|
|
<literal><property/></literal> element.<programlisting
|
|
language="myxml"><object id="theTargetObject" type="...">
|
|
. . .
|
|
</object>
|
|
|
|
<object id="theClientObject" type="...">
|
|
<property name="targetName">
|
|
<idref object="theTargetObject"/>
|
|
</property>
|
|
</object></programlisting>This above object definition snipped is
|
|
<emphasis>exactly</emphasis> equivalent (at runtime) to the
|
|
following snippit:<programlisting language="myxml"><object id="theTargetObject" type="...">
|
|
. . .
|
|
</object>
|
|
|
|
<object id="theClientObject" type="...">
|
|
<property name="targetName" value="theTargetObject"/>
|
|
</object></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"><property name="targetName">
|
|
<idref local="theTargetObject"/>
|
|
</property></programlisting></para>
|
|
</sect4>
|
|
|
|
<sect4>
|
|
<title>Whitespace Handling</title>
|
|
|
|
<para>Usually all leading and trailing whitespaces are trimmed from
|
|
a <value /> element's text. In some cases it is necessary to
|
|
maintain whitespaces exactly as they are written into the xml
|
|
element. The parser does understand the xml:space attribute in this
|
|
case:</para>
|
|
|
|
<programlisting language="myxml"><property name="myProp">
|
|
<value xml:space="preserve"> &#x000a;&#x000d;&#x0009;</value>
|
|
</property></programlisting>
|
|
|
|
<para>The above configuration will result in the string " \n\r\t".
|
|
Note, that you don't have to explicitely specifiy the 'xml'
|
|
namespace on top of your configuration.</para>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-ref-element">
|
|
<title>References to other objects (collaborators)</title>
|
|
|
|
<para>The <literal>ref</literal> element is the final element allowed
|
|
inside a <literal><constructor-arg/> or
|
|
<property/></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"><ref object="someObject"/></programlisting></para>
|
|
|
|
<para>Specifying the target object by using the
|
|
<literal>local</literal> attribute leverages the ability of the XML
|
|
parser to validate XML id references within the same file. The value
|
|
of the <literal>local</literal> attribute must be the same as the
|
|
<literal>id</literal> attribute of the target object. The XML parser
|
|
will issue an error if no matching element is found in the same file.
|
|
As such, using the local variant is the best choice (in order to know
|
|
about errors are early as possible) if the target object is in the
|
|
same XML file.<programlisting language="myxml"><ref local="someObject"/></programlisting></para>
|
|
|
|
<para>Specifying the target object 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"><!-- in the parent context -->
|
|
<object id="AccountService" type="MyApp.SimpleAccountService, MyApp">
|
|
<!-- insert dependencies as required as here -->
|
|
</object></programlisting><programlisting language="myxml"><!-- in the child (descendant) context -->
|
|
<object id="AccountService" <-- notice that the name of this object is the same as the name of the 'parent' object
|
|
type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
|
|
<property name="target">
|
|
<ref parent="AccountService"/> <-- notice how we refer to the parent object -->
|
|
</property>
|
|
<!-- insert other configuration and dependencies as required as here -->
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-inline-object">
|
|
<title>Inner objects</title>
|
|
|
|
<para>An <literal><object/></literal> element inside the
|
|
<<literal>constructor-arg/> or <property/></literal>
|
|
element defines so called inner object.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="outer" type="...">
|
|
|
|
<!-- Instead of using a reference to target, just use an inner object -->
|
|
|
|
<property name="target">
|
|
<object type="ExampleApp.Person, ExampleApp">
|
|
<property name="name" value="Tony"/>
|
|
<property name="age" value="51"/>
|
|
</object>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<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"><objects xmlns="http://www.springframework.net">
|
|
<object id="moreComplexObject" type="Example.ComplexObject">
|
|
<!--
|
|
results in a call to the setter of the SomeList (System.Collections.IList) property
|
|
-->
|
|
<property name="SomeList">
|
|
<list>
|
|
<value>a list element followed by a reference</value>
|
|
<ref object="myConnection"/>
|
|
</list>
|
|
</property>
|
|
<!--
|
|
results in a call to the setter of the SomeDictionary (System.Collections.IDictionary) property
|
|
-->
|
|
<property name="SomeDictionary">
|
|
<dictionary>
|
|
<entry key="a string => string entry" value="just some string"/>
|
|
<entry key-ref="myKeyObject" value-ref="myConnection"/>
|
|
</dictionary>
|
|
</property>
|
|
<!--
|
|
results in a call to the setter of the SomeNameValue (System.Collections.NameValueCollection) property
|
|
-->
|
|
<property name="SomeNameValue">
|
|
<name-values>
|
|
<add key="HarryPotter" value="The magic property"/>
|
|
<add key="JerrySeinfeld" value="The funny (to Americans) property"/>
|
|
</name-values>
|
|
</property>
|
|
<!--
|
|
results in a call to the setter of the SomeSet (Spring.Collections.ISet) property
|
|
-->
|
|
<property name="someSet">
|
|
<set>
|
|
<value>just some string</value>
|
|
<ref object="myConnection"/>
|
|
</set>
|
|
</property>
|
|
</object>
|
|
</objects></programlisting></para>
|
|
|
|
<para>Many classes in the BCL expose only read-only properties for
|
|
collection classes. When Spring.NET encounters a read-only collection,
|
|
it will configure the collection by using the getter property to
|
|
obtain a reference to the collection class and then proceed to add the
|
|
additional elements to the existing collection. This results in an
|
|
additive behavior for collection properties that are exposed in this
|
|
manner.</para>
|
|
|
|
<para><emphasis>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<T></literal> and <literal>IDictionary<TKey,
|
|
TValue></literal>. The type parameter for these collections is
|
|
specified by using the XML attribute <literal>element-type</literal>
|
|
for <literal>IList<T></literal> and the XML attributes
|
|
<literal>key-type</literal> and <literal>value-type</literal> for
|
|
<literal>IDictionary<TKey, TValue></literal>. The values of the
|
|
collection are automaticaly converted from a string to the appropriate
|
|
type. If you are using your own user-defined type as a generic type
|
|
parameter you will likely need to register a custom type converter.
|
|
Refer to <xref linkend="objects-type-conversion" /> for more
|
|
information. The implementations of <literal>IList<T></literal>
|
|
and <literal>IDictionary<TKey, TValue></literal> that is created
|
|
are <literal>System.Collections.Generic.List</literal> and
|
|
<literal>System.Collections.Generic.Dictionary</literal>.</para>
|
|
|
|
<para>The following class represents a lottery ticket and demonstrates
|
|
how to set the values of a generic IList. <programlisting
|
|
language="csharp">public class LotteryTicket {
|
|
|
|
List<int> list;
|
|
|
|
DateTime date;
|
|
|
|
public List<int> Numbers {
|
|
set { list = value; }
|
|
get { return list; }
|
|
}
|
|
|
|
public DateTime Date {
|
|
get { return date; }
|
|
set { date = value; }
|
|
}
|
|
}</programlisting> The XML fragment that can be used to configure this class
|
|
is shown below <programlisting language="myxml"><object id="MyLotteryTicket" type="GenericsPlay.Lottery.LotteryTicket, GenericsPlay">
|
|
<property name="Numbers">
|
|
<list element-type="int">
|
|
<value>11</value>
|
|
<value>21</value>
|
|
<value>23</value>
|
|
<value>34</value>
|
|
<value>36</value>
|
|
<value>38</value>
|
|
</list>
|
|
</property>
|
|
<property name="Date" value="4/16/2006"/>
|
|
</object></programlisting></para>
|
|
|
|
<para>The following shows the definition of a more complex class that
|
|
demonstrates the use of generics using the
|
|
<literal>Spring.Expressions.IExpression</literal> interface as the
|
|
generic type parameter for the IList element-type and the value-type
|
|
for IDictionary. <literal>Spring.Expressions.IExpression</literal> has
|
|
an associated type converter,
|
|
<literal>Spring.Objects.TypeConverters.ExpressionConverter</literal>
|
|
that is already pre-registered with Spring. <programlisting
|
|
language="csharp"> public class GenericExpressionHolder
|
|
{
|
|
private System.Collections.Generic.IList<IExpression> expressionsList;
|
|
|
|
private System.Collections.Generic.IDictionary<string,IExpression> expressionsDictionary;
|
|
|
|
public System.Collections.Generic.IList<IExpression> ExpressionsList
|
|
{
|
|
set { this.expressionsList = value; }
|
|
}
|
|
|
|
public System.Collections.Generic.IDictionary<string, IExpression> ExpressionsDictionary
|
|
{
|
|
set { this.expressionsDictionary = value; }
|
|
}
|
|
|
|
public IExpression this[int index]
|
|
{
|
|
get
|
|
{
|
|
return this.expressionsList[index];
|
|
}
|
|
}
|
|
|
|
public IExpression this[string key]
|
|
{
|
|
get { return this.expressionsDictionary[key]; }
|
|
}
|
|
}</programlisting> An example XML configuration of this class is shown
|
|
below <programlisting language="myxml"><object id="genericExpressionHolder"
|
|
type="Spring.Objects.Factory.Xml.GenericExpressionHolder,
|
|
Spring.Core.Tests">
|
|
<property name="ExpressionsList">
|
|
<list element-type="Spring.Expressions.IExpression, Spring.Core">
|
|
<value>1 + 1</value>
|
|
<value>date('1856-7-9').Month</value>
|
|
<value>'Nikola Tesla'.ToUpper()</value>
|
|
<value>DateTime.Today > date('1856-7-9')</value>
|
|
</list>
|
|
</property>
|
|
<property name="ExpressionsDictionary">
|
|
<dictionary key-type="string" value-type="Spring.Expressions.IExpression, Spring.Core">
|
|
<entry key="zero">
|
|
<value>1 + 1</value>
|
|
</entry>
|
|
<entry key="one">
|
|
<value>date('1856-7-9').Month</value>
|
|
</entry>
|
|
<entry key="two">
|
|
<value>'Nikola Tesla'.ToUpper()</value>
|
|
</entry>
|
|
<entry key="three">
|
|
<value>DateTime.Today > date('1856-7-9')</value>
|
|
</entry>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<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><list/></literal>,
|
|
<literal><dictionary/></literal>,
|
|
<literal><set/></literal> or
|
|
<literal><name-value/></literal> element, and have child-style
|
|
<literal><list/></literal>,
|
|
<literal><dictionary/></literal>,
|
|
<literal><set/></literal> or
|
|
<literal><name-value/></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"><object id="parent" abstract="true" type="Example.ComplexObject, Examples">
|
|
<property name="AdminEmails">
|
|
<name-values>
|
|
<add key="administrator" value="administrator@example.com"/>
|
|
<add key="support" value="support@example.com"/>
|
|
</name-values>
|
|
</property>
|
|
</object>
|
|
|
|
<object id="child" parent="parent" >
|
|
<property name="AdminEmails">
|
|
<!-- the merge is specified on the *child* collection definition -->
|
|
<name-values merge="true">
|
|
<add key="sales" value="sales@example.com"/>
|
|
<add key="support" value="support@example.co.uk"/>
|
|
</name-values>
|
|
</property>
|
|
</object></programlisting>
|
|
|
|
<para>Notice the use of the <literal>merge=true</literal> attribute on
|
|
the <literal><name-values/></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><name-values/></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><list/></literal>,
|
|
<literal><dictionary/></literal>, and
|
|
<literal><set/></literal> collection types. In the specific case
|
|
of the <literal><list/></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><object type="Examples.ExampleObject, ExamplesLibrary">
|
|
<property name="email" value=""/>
|
|
</object></programlisting>
|
|
|
|
<para>This results in the email property being set to the empty string
|
|
value (<literal>""</literal>), in much the same way as can be seen in
|
|
the following snippet of C# code</para>
|
|
|
|
<programlisting language="csharp">exampleObject.Email = "";</programlisting>
|
|
|
|
<para>The <literal><null></literal> element is used to handle
|
|
<literal>null</literal> values. For example:</para>
|
|
|
|
<programlisting language="myxml"><object type="Examples.ExampleObject, ExamplesLibrary">
|
|
<property name="email"><null/></property>
|
|
</object></programlisting>
|
|
|
|
<para>This results in the email property being set to
|
|
<literal>null</literal>, again in much the same way as can be seen in
|
|
the following snippet of C# code:<programlisting language="csharp">exampleObject.Email = null;</programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Setting indexer properties</title>
|
|
|
|
<para>An indexer lets you set and get values from a collection using a
|
|
familiar bracket <literal>[]</literal> notation. Spring's XML
|
|
configuration supports the setting of indexer properties. Overloaded
|
|
indexers as well as multiparameter indexers are also supported. The
|
|
property expression parser described in <xref linkend="expressions" />
|
|
is used to perform the type conversion of the indexer name argument
|
|
from a string in the XML file to a matching target type. As an example
|
|
consider the following class <programlisting language="csharp">public class Person
|
|
{
|
|
private IList favoriteNames = new ArrayList();
|
|
|
|
private IDictionary properties = new Hashtable();
|
|
|
|
public Person()
|
|
{
|
|
favoriteNames.Add("p1");
|
|
favoriteNames.Add("p2");
|
|
}
|
|
|
|
public string this[int index]
|
|
{
|
|
get { return (string) favoriteNames[index]; }
|
|
set { favoriteNames[index] = value; }
|
|
}
|
|
|
|
public string this[string keyName]
|
|
{
|
|
get { return (string) properties[keyName]; }
|
|
set { properties.Add(keyName, value); }
|
|
}
|
|
}</programlisting> The XML configuration snippet to populate this object with
|
|
data is shown below <programlisting language="myxml"><object id="person" type="Test.Objects.Person, Test.Objects">
|
|
<property name="[0]" value="Master Shake"/>
|
|
<property name="['one']" value="uno"/>
|
|
</object></programlisting></para>
|
|
|
|
<note>
|
|
<para>The use of the property expression parser in Release 1.0.2
|
|
changed how you configure indexer properties. The following section
|
|
describes this usage.</para>
|
|
|
|
<para>The older style configuration uses the following syntax
|
|
<programlisting language="myxml"><object id="objectWithIndexer" type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="Item[0]" value="my string value"/>
|
|
</object></programlisting> You can also change the name used to identify
|
|
the indexer by adorning your indexer method declaration with the
|
|
attribute <literal>[IndexerName("MyItemName")]</literal>. You would
|
|
then use the string <literal>MyItemName[0]</literal> to configure
|
|
the first element of that indexer.</para>
|
|
|
|
<para>There are some limitations to be aware in the older indexer
|
|
configuration. The indexer can only be of a single parameter that is
|
|
convertible from a string to the indexer parameter type. Also,
|
|
multiple indexers are not supported. You can get around that last
|
|
limitation currently if you use the IndexerName attribute.</para>
|
|
</note>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-shortcutforms">
|
|
<title>Value and ref shortcut forms</title>
|
|
|
|
<para>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"><property name="myProperty">
|
|
<value>hello</value>
|
|
</property>
|
|
|
|
<constructor-arg>
|
|
<value>hello</value>
|
|
</constructor-arg>
|
|
|
|
<entry key="myKey">
|
|
<value>hello</value>
|
|
</entry></programlisting> are equivalent to:<programlisting
|
|
language="myxml"><property name="myProperty" value="hello"/>
|
|
|
|
<constructor-arg value="hello"/>
|
|
|
|
<entry key="myKey" value="hello"/></programlisting> In general, when
|
|
typing definitions by hand, you will probably prefer to use the less
|
|
verbose shortcut form.</para>
|
|
|
|
<para>The <literal>property</literal> and
|
|
<literal>constructor-arg</literal> elements support a similar shortcut
|
|
<literal>ref</literal> attribute which may be used instead of a full
|
|
nested <literal>ref</literal> element. Therefore, the following...
|
|
<programlisting language="myxml"><property name="myProperty">
|
|
<ref object="anotherObject"/>
|
|
</property>
|
|
|
|
<constructor-arg index="0">
|
|
<ref object="anotherObject"/>
|
|
</constructor-arg></programlisting> is equivalent to... <programlisting
|
|
language="myxml"><property name="myProperty" ref="anotherObject"/>
|
|
|
|
<constructor-arg index="0" ref="anotherObject"/></programlisting></para>
|
|
|
|
<note>
|
|
<para>The shortcut form is equivalent to a <literal><ref
|
|
object="xxx"></literal> element; there is no shortcut for either
|
|
the <literal><ref local="xxx"></literal> or <literal><ref
|
|
parent="xxx"></literal> elements. For a local or parent
|
|
<literal>ref</literal>, you must still use the long form.</para>
|
|
</note>
|
|
|
|
<para>Finally, the entry element allows a shortcut form the specify
|
|
the key and/or value of a dictionary, in the form of key/key-ref and
|
|
value/value-ref attributes. Therefore, the following <programlisting
|
|
language="myxml"><entry>
|
|
<key>
|
|
<ref object="MyKeyObject"/>
|
|
</key>
|
|
<ref object="MyValueObject"/>
|
|
</entry></programlisting> Is equivalent to: <programlisting
|
|
language="myxml"><entry key-ref="MyKeyObject" value-ref="MyValueObject"/></programlisting>
|
|
As mentioned previously, the equivalence is to <literal><ref
|
|
object="xxx"></literal> and not the local or parent forms of object
|
|
references.</para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-referencing-compound-properties">
|
|
<title>Compound property names and Spring expression
|
|
references</title>
|
|
|
|
<para>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"><object id="foo" type="Spring.Foo, Spring.Foo">
|
|
<property name="bar.baz.name" value="Bingo"/>
|
|
</object></programlisting>
|
|
|
|
<para>As an example of some alternative ways to declare the property
|
|
name, you can use SpEL's support for indexers to configure a
|
|
Dictionary key value pair as an alternative to the nested
|
|
<literal><dictionary></literal> element. More importantly, you
|
|
can use the 'expression' element to refer to a Spring expression as
|
|
the value of the property. Simple examples of this are shown
|
|
below</para>
|
|
|
|
<programlisting language="myxml"><property name=“minValue” expression=“int.MinValue” />
|
|
|
|
<property name=“weekFromToday” expression="DateTime.Today + 7"/></programlisting>
|
|
|
|
<para>Using SpEL's support for method evaluation, you can easily call
|
|
static method on various helper classes in your XML
|
|
configuraiton.</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Declarative Event Listener Registration</title>
|
|
|
|
<para>In C# events are built right into the language thanks to the
|
|
<literal>event</literal> keyword. Under the scenes, events are
|
|
essentially a shorthand notation for delegates with some additional
|
|
guidelines as to what the parameters to an event handler method should
|
|
be (i.e. a sender <literal>System.Object</literal> and an
|
|
<literal>System.EventArgs</literal> object).</para>
|
|
|
|
<para><programlisting language="csharp">public class EventSource
|
|
public event EventHandler Click;</programlisting></para>
|
|
|
|
<para>In use, .NET events are combined with one or more event handler
|
|
methods. Each handler method is programmatically added, or removed, from
|
|
the event and corresponds to an object's method that should be invoked
|
|
when a particular event occurs. When more than one handler method is
|
|
added to an event, then each of the registered methods will be invoked
|
|
in turn when an event occurs.</para>
|
|
|
|
<para><programlisting language="csharp">TestObject source = new TestObject();
|
|
TestEventHandler eventListener1 = new TestEventHandler();
|
|
TestEventHandler eventListener2 = new TestEventHandler();
|
|
|
|
source.Click += eventListener1.HandleEvent; // Adding the first event handler method to the event
|
|
source.Click += eventListener2.HandleEvent; // Adding a second event handler method to the event
|
|
|
|
source.OnClick(); // First eventListener1.HandleEvent is invoked, then eventListener2.HandleEvent</programlisting></para>
|
|
|
|
<para>When OnClick() is invoked, the event is fired.</para>
|
|
|
|
<para><programlisting language="csharp">public void OnClick()
|
|
{
|
|
if (Click != null)
|
|
{
|
|
Click(this, EventArgs.Empty); // Fire the event off to the registered handler methods
|
|
}
|
|
}</programlisting></para>
|
|
|
|
<para>One of the not so nice things about using events is that, without
|
|
employing late binding, you declare the objects that are registered with
|
|
a particular event programmatically. Spring .NET offers a way to
|
|
declaratively register your handler methods with particular events using
|
|
the <literal><listener></literal> element inside your
|
|
<literal><object></literal> elements.</para>
|
|
|
|
<sect3>
|
|
<title>Declarative event handlers</title>
|
|
|
|
<para>Rather than having to specifically declare in your code that you
|
|
are adding a method to be invoked on an event, using the
|
|
<literal><listener></literal> element you can register a plain
|
|
object's methods with the corresponding event declaratively in your
|
|
application configuration.</para>
|
|
|
|
<para>Using the <literal>listener</literal> element you can:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<link linkend="objects-simple-event-configuration">Configure a
|
|
method to be invoked when an event is fired.</link>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<link linkend="objects-handler-reg-ex-configuration">Register a
|
|
collection of handler methods based on a regular
|
|
expression.</link>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<link linkend="objects-event-name-reg-ex-configuration">Register
|
|
a handler method against an event name that contains a regular
|
|
expression.</link>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-simple-event-configuration">
|
|
<title>Configuring a method to be invoked when an event is
|
|
fired</title>
|
|
|
|
<para>The same event registration in the example above can be achieved
|
|
using configuration using the <literal><listener></literal>
|
|
element.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="eventListener1" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<!-- wired up to an event exposed on an instance -->
|
|
<listener event="Click" method="HandleEvent">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object>
|
|
|
|
<object id="eventListener2" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<!-- wired up to an event exposed on an instance -->
|
|
<listener event="Click" method="HandleEvent">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object></programlisting></para>
|
|
|
|
<para>In this case the two different objects will have their
|
|
<literal>HandleEvent</literal> method invoked, as indicated explicitly
|
|
using the <literal>method</literal> attribute, when a
|
|
<literal>Click</literal> event, as specified by the
|
|
<literal>event</literal> attribute, is triggered on the object
|
|
referred to by the <literal>ref</literal> element.</para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-handler-reg-ex-configuration">
|
|
<title>Registering a collection of handler methods based on a regular
|
|
expression</title>
|
|
|
|
<para>Regular expressions can be employed to wire up more than one
|
|
handler method to an object that contains one or more events.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<listener method="Handle.+">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object></programlisting></para>
|
|
|
|
<para>Here all the <literal>eventListener</literal>'s handler methods
|
|
that begin with 'Handle', and that have the corresponding two
|
|
parameters of a <literal>System.Object</literal> and a
|
|
<literal>System.EventArgs</literal>, will be registered against all
|
|
events exposed by the <literal>source</literal> object.</para>
|
|
|
|
<para>You can also use the name of the event in regular expression to
|
|
filter your handler methods based on the type of event
|
|
triggered.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<!-- For the Click event, the HandleClick handler method will be invoked. -->
|
|
<listener method="Handle${event}">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-event-name-reg-ex-configuration">
|
|
<title>Registering a handler method against an event name that
|
|
contains a regular expression</title>
|
|
|
|
<para>Finally, you can register an object's handler methods against a
|
|
selection of events, filtering based on their name using a regular
|
|
expression.</para>
|
|
|
|
<para><programlisting language="myxml"><object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample">
|
|
<listener method="HandleEvent" event="Cl.+">
|
|
<ref object="source"/>
|
|
</listener>
|
|
</object></programlisting></para>
|
|
|
|
<para>In this example the <literal>eventListener</literal>'s
|
|
<literal>HandleEvent</literal> handler method will be invoked for any
|
|
event that begins with 'Cl'.</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-factory-dependson">
|
|
<title>Using <literal>depends-on</literal></title>
|
|
|
|
<para>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><ref/></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"><object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager">
|
|
<property name="manager" ref="manager"/>
|
|
</object>
|
|
|
|
<object id="manager" type="Examples.ManagerObject, ExamplesLibrary"/></programlisting></para>
|
|
|
|
<para>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"><object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager,accountDao">
|
|
<property name="manager" ref="manager" />
|
|
</object>
|
|
|
|
<object id="manager" type="Examples.ManagerObject, ExamplesLibrary" />
|
|
<object id="accountDao" type="Examples.AdoAccountDao, ExamplesLibrary" /></programlisting>
|
|
|
|
<note>
|
|
<para>The <literal>depends-on</literal> attribute 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><object/></literal> element; for example:</para>
|
|
|
|
<programlisting language="myxml"><object id="lazy" type="MyCompany.ExpensiveToCreateObject, MyApp" lazy-init="true"/>
|
|
|
|
<object name="not.lazy" type="MyCompany.AnotherObject, MyApp"/></programlisting>
|
|
|
|
<para>When the 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><objects/></literal> element; for example:</para>
|
|
|
|
<programlisting language="myxml"><objects default-lazy-init="true">
|
|
<!-- no objects will be pre-instantiated... -->
|
|
</objects></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-factory-autowire">
|
|
<title>Autowiring collaborators</title>
|
|
|
|
<para>The Spring container is able to autowire relationships between
|
|
collaborating objects. This means that it is possible to automatically
|
|
let Spring resolve collaborators (other objects) for your object by
|
|
inspecting the contents of the IoC container.. The autowiring
|
|
functionality has five modes. Autowiring is specified per object and can
|
|
thus be enabled for some object, while other objects will not be
|
|
autowired. Using autowiring, it is possible to reduce or eliminate the
|
|
need to specify properties or constructor arguments, thus saving a
|
|
significant amount of typing. When using XML-based configuration
|
|
metadata, the autowire mode for an object definition is specified by
|
|
using the autowire attribute of the <object/> element. The
|
|
following values are allowed:</para>
|
|
|
|
<para><table frame="all">
|
|
<title>Autowiring modes</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="1*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Mode</entry>
|
|
|
|
<entry>Explanation</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>no</entry>
|
|
|
|
<entry>No autowiring at all. This is the default value and you
|
|
are encouraged not to change this for large applications,
|
|
since specifying your collaborators explicitly gives you a
|
|
feeling for what you're actually doing (always a bonus) and is
|
|
a great way of somewhat documenting the structure of your
|
|
system.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>byName</entry>
|
|
|
|
<entry>This option will inspect the objects within the
|
|
container, and look for an object named exactly the same as
|
|
the property which needs to be autowired. For example, if you
|
|
have an object definition that is set to autowire by name, and
|
|
it contains a <literal>Master</literal> property, Spring.NET
|
|
will look for an object definition named
|
|
<literal>Master</literal>, and use it as the value of the
|
|
<literal>Master</literal> property on your object
|
|
definition.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>byType</entry>
|
|
|
|
<entry>This option gives you the ability to resolve
|
|
collaborators by type instead of by name. Supposing you have
|
|
an <literal>IObjectDefinition</literal> with a collaborator
|
|
typed <literal>SqlConnection</literal>, Spring.NET will search
|
|
the entire object factory for an object definition of type
|
|
<literal>SqlConnection</literal> and use it as the
|
|
collaborator. <emphasis>If 0 (zero) or more than 1 (one)
|
|
object definitions of the desired type exist in the container,
|
|
a failure will be reported and you won't be able to use
|
|
autowiring for that specific object.</emphasis></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>constructor</entry>
|
|
|
|
<entry>This is analogous to <emphasis>byType</emphasis>, but
|
|
applies to constructor arguments. If there isn't exactly one
|
|
object of the constructor argument type in the object factory,
|
|
a fatal error is raised.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>autodetect</entry>
|
|
|
|
<entry>Chooses <emphasis>constructor</emphasis> or
|
|
<emphasis>byType</emphasis> through introspection of the
|
|
object class. If a default constructor is found,
|
|
<emphasis>byType</emphasis> gets applied.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
|
|
<para>Note that explicit dependencies in property and constructor-arg
|
|
settings always override autowiring. Please also note that it is not
|
|
currently possible to autowire so-called simple properties such as
|
|
primitives, Strings, and Types (and arrays of such simple properties).
|
|
(This is by-design and should be considered a feature.) When using
|
|
either the byType or constructor autowiring mode, it is possible to wire
|
|
arrays and typed-collections. In such cases all autowire candidates
|
|
within the container that match the expected type will be provided to
|
|
satisfy the dependency. Strongly-typed IDictionaries can even be
|
|
autowired if the expected key type is string. An autowired IDictionary
|
|
values will consist of all object instances that match the expected
|
|
type, and the IDictionary's keys will contain the corresponding object
|
|
names.</para>
|
|
|
|
<para>Autowire behavior can be combined with dependency checking, which
|
|
will be performed after all autowiring has been completed. It is
|
|
important to understand the various advantages and disadvantages of
|
|
autowiring. Some advantages of autowiring include:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Autowiring can significantly reduce the volume of
|
|
configuration required. However, mechanisms such as the use of a
|
|
object template (discussed elsewhere in this chapter) are also
|
|
valuable in this regard.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Autowiring can cause configuration to keep itself up to date
|
|
as your objects evolve. For example, if you need to add an
|
|
additional dependency to a class, that dependency can be satisfied
|
|
automatically without the need to modify configuration. Thus there
|
|
may be a strong case for autowiring during development, without
|
|
ruling out the option of switching to explicit wiring when the code
|
|
base becomes more stable.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Some disadvantages of autowiring:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Autowiring is more magical than explicit wiring. Although, as
|
|
noted in the above table, Spring is careful to avoid guessing in
|
|
case of ambiguity which might have unexpected results, the
|
|
relationships between your Spring-managed objects are no longer
|
|
documented explicitly.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Wiring information may not be available to tools that may
|
|
generate documentation from a Spring container.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Another issue to consider when autowiring by type is that multiple
|
|
object definitions within the container may match the type specified by
|
|
the setter method or constructor argument to be autowired. For arrays,
|
|
collections, or IDictionary, this is not necessarily a problem. However
|
|
for dependencies that expect a single value, this ambiguity will not be
|
|
arbitrarily resolved. Instead, if no unique object definition is
|
|
available, an Exception will be thrown.</para>
|
|
|
|
<para>When deciding whether to use autowiring, there is no wrong or
|
|
right answer in all cases. A degree of consistency across a project is
|
|
best though; for example, if autowiring is not used in general, it might
|
|
be confusing to developers to use it just to wire one or two object
|
|
definitions.</para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-factory-dependencies">
|
|
<title>Checking for dependencies</title>
|
|
|
|
<para>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"><public|protected> [abstract] <return-type> 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"><!-- a stateful object deployed as a prototype (non-singleton) -->
|
|
<object id="command" class="Fiona.Apple.AsyncCommand, Fiona" singleton="false">
|
|
<!-- inject dependencies here as required -->
|
|
</object>
|
|
|
|
<!-- commandProcessor uses a statefulCommandHelpder -->
|
|
<object id="commandManager" type="Fiona.Apple.CommandManager, Fiona">
|
|
<lookup-method name="CreateCommand" object="command"/>
|
|
</object></programlisting>
|
|
|
|
<para>The object identified as <literal>commandManager</literal> will
|
|
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">/// <summary>
|
|
/// Meant to be used to override the existing ComputeValue(string)
|
|
/// implementation in MyValueCalculator.
|
|
/// </summary>
|
|
public class ReplacementComputeValue : IMethodReplacer
|
|
{
|
|
public object Implement(object target, MethodInfo method, object[] arguments)
|
|
{
|
|
// get the input value, work with it, and return a computed result...
|
|
string value = (string) arguments[0];
|
|
// compute...
|
|
return result;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>The object definition to deploy the original class and specify
|
|
the method override would look like this:</para>
|
|
|
|
<programlisting language="myxml"><object id="myValueCalculator" type="Examples.MyValueCalculator, ExampleAssembly">
|
|
<!-- arbitrary method replacement -->
|
|
<replaced-method name="ComputeValue" replacer="replacementComputeValue">
|
|
<arg-type match="String"/>
|
|
</replaced-method>
|
|
</object>
|
|
|
|
<object id="replacementComputeValue" type="Examples.ReplacementComputeValue, ExampleAssembly"/></programlisting>
|
|
|
|
<para>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"><object name="person" type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="age" value="20"/>
|
|
<property name="spouse">
|
|
<object type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="age" value="21"/>
|
|
</object>
|
|
</property>
|
|
</object>
|
|
|
|
// will result in 21, which is the value of property 'spouse.age' of object 'person'
|
|
<object name="theAge" type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="person"/>
|
|
<property name="TargetProperty" value="spouse.age"/>
|
|
</object></programlisting></para>
|
|
|
|
<para>An example of using a
|
|
<literal>PropertyRetrievingFactoryObject</literal> to evaluate a
|
|
<literal>static</literal> property is shown below.</para>
|
|
|
|
<programlisting language="myxml"><object id="cultureAware"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
|
|
<property name="culture" ref="cultureFactory"/>
|
|
</object>
|
|
|
|
<object id="cultureFactory"
|
|
type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
|
|
<property name="StaticProperty">
|
|
<value>System.Globalization.CultureInfo.CurrentUICulture, Mscorlib</value>
|
|
</property>
|
|
</object></programlisting>
|
|
|
|
<para>Similarly, an example showing the use of an instance property is
|
|
shown below.</para>
|
|
|
|
<programlisting language="myxml"><object id="instancePropertyCultureAware"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
|
|
<property name="Culture" ref="instancePropertyCultureFactory"/>
|
|
</object>
|
|
|
|
<object id="instancePropertyCultureFactory"
|
|
type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="instancePropertyCultureAwareSource"/>
|
|
<property name="TargetProperty" value="MyDefaultCulture"/>
|
|
</object>
|
|
|
|
<object id="instancePropertyCultureAwareSource"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/>
|
|
</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Setting a reference to the value of field.</title>
|
|
|
|
<para>The <literal>FieldRetrievingFactoryObject</literal> class
|
|
addresses much the same area of concern as the
|
|
<literal>PropertyRetrievingFactoryObject</literal> described in the
|
|
previous section. However, as its name might suggest, the
|
|
<literal>FieldRetrievingFactoryObject</literal> class is concerned
|
|
with looking up the value of a <emphasis role="bold">public</emphasis>
|
|
field exposed on either an instance or a class (and similarly, in the
|
|
case of a field exposed on a class, the field must obviously be
|
|
static).</para>
|
|
|
|
<para>The following example demonstrates using a
|
|
<literal>FieldRetrievingFactoryObject</literal> to look up the value
|
|
of a (public, static) field exposed on a class</para>
|
|
|
|
<para><programlisting language="myxml"><object id="withTypesField"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
|
|
<property name="Types" ref="emptyTypesFactory"/>
|
|
</object>
|
|
|
|
<object id="emptyTypesFactory"
|
|
type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core">
|
|
<property name="TargetType" value="System.Type, Mscorlib"/>
|
|
<property name="TargetField" value="EmPTytypeS"/>
|
|
</object>
|
|
</programlisting></para>
|
|
|
|
<para>The example in the next section demonstrates the look up of a
|
|
(public) field exposed on an object instance.</para>
|
|
|
|
<programlisting language="myxml"><object id="instanceCultureAware"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
|
|
<property name="Culture" ref="instanceCultureFactory"/>
|
|
</object>
|
|
|
|
<object id="instanceCultureFactory"
|
|
type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="instanceCultureAwareSource"/>
|
|
<property name="TargetField" value="Default"/>
|
|
</object>
|
|
|
|
<object id="instanceCultureAwareSource"
|
|
type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/>
|
|
</programlisting>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-methodfactory">
|
|
<title>Setting a property or constructor argument to the return value
|
|
of a method invocation.</title>
|
|
|
|
<para>The <literal>MethodInvokingFactoryObject</literal> rounds out
|
|
the trio of classes that permit the setting of properties and
|
|
constructor arguments using the members of other objects and classes.
|
|
Whereas the <literal>PropertyRetrievingFactoryObject</literal> and
|
|
<literal>FieldRetrievingFactoryObject</literal> classes dealt with
|
|
simply looking up and returning the value of property or field on an
|
|
object or class, the <literal>MethodInvokingFactoryObject</literal>
|
|
allows one to set a constructor or property to the return value of an
|
|
arbitrary method invocation,</para>
|
|
|
|
<para>The <literal>MethodInvokingFactoryObject</literal> class handles
|
|
both the case of invoking an (instance) method on another object in
|
|
the container, and the case of a static method call on an arbitrary
|
|
class. Additionally, it is sometimes necessary to invoke a method just
|
|
to perform some sort of initialization.... while the mechanisms for
|
|
handling object initialization have yet to be introduced (see <xref
|
|
linkend="objects-factory-lifecycle-initializingobject" />), these
|
|
mechanisms do not permit any arguments to be passed to any
|
|
initialization method, and are confined to invoking an initialization
|
|
method on the object that has just been instantiated by the container.
|
|
The <literal>MethodInvokingFactoryObject</literal> allows one to
|
|
invoke pretty much <emphasis role="bold">any</emphasis> method on any
|
|
object (or class in the case of a static method).</para>
|
|
|
|
<para>The following example (in an XML based
|
|
<literal>IObjectFactory</literal> definition) uses the
|
|
<literal>MethodInvokingFactoryObject</literal> class to force a call
|
|
to a static factory method prior to the instantiation of the
|
|
object...</para>
|
|
|
|
<para><programlisting language="myxml"><object id="force-init"
|
|
type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="StaticMethod">
|
|
<value>ExampleNamespace.ExampleInitializerClass.Initialize</value>
|
|
</property>
|
|
</object>
|
|
<object id="myService" depends-on="force-init"/></programlisting> Note
|
|
that the definition for the <literal>myService</literal> object has
|
|
used the <literal>depends-on</literal> attribute to refer to the
|
|
<literal>force-init</literal> object, which will force the
|
|
initialization of the <literal>force-init</literal> object first (and
|
|
thus the calling of its configured <literal>StaticMethod</literal>
|
|
static initializer method, when <literal>myService</literal> is first
|
|
initialized. Please note that in order to effect this initialization,
|
|
the <literal>MethodInvokingFactoryObject</literal> object <emphasis
|
|
role="bold">must</emphasis> be operating in
|
|
<literal>singleton</literal> mode (the default.. see the next
|
|
paragraph).</para>
|
|
|
|
<para>Note that since this class is expected to be used primarily for
|
|
accessing factory methods, this factory defaults to operating in
|
|
<literal>singleton</literal> mode. As such, as soon as all of the
|
|
properties for a <literal>MethodInvokingFactoryObject</literal> object
|
|
have been set, and if the
|
|
<literal>MethodInvokingFactoryObject</literal> object is still in
|
|
<literal>singleton</literal> mode, the method will be invoked
|
|
immediately and the return value cached for later access. The first
|
|
request by the container for the factory to produce an object will
|
|
cause the factory to return the cached return value for the current
|
|
request (and all subsequent requests). The
|
|
<methodname>IsSingleton</methodname> property may be set to false, to
|
|
cause this factory to invoke the target method each time it is asked
|
|
for an object (in this case there is obviously no caching of the
|
|
return value).</para>
|
|
|
|
<para>A static target method may be specified by setting the
|
|
<methodname>targetMethod</methodname> property to a string
|
|
representing the static method name, with
|
|
<methodname>TargetType</methodname> specifying the
|
|
<literal>Type</literal> that the static method is defined on.
|
|
Alternatively, a target instance method may be specified, by setting
|
|
the <methodname>TargetObject</methodname> property to the name of
|
|
another Spring.NET managed object definition (the target object), and
|
|
the <methodname>TargetMethod</methodname> property to the name of the
|
|
method to call on that target object.</para>
|
|
|
|
<para>Arguments for the method invocation may be specified in two ways
|
|
(or even a mixture of both)... the first involves setting the
|
|
<methodname>Arguments</methodname> property to the list of arguments
|
|
for the method that is to be invoked. Note that the ordering of these
|
|
arguments is significant... the order of the values passed to the
|
|
<methodname>Arguments</methodname> property must be the same as the
|
|
order of the arguments defined on the method signature, including the
|
|
argument <literal>Type</literal>. This is shown in the example below
|
|
<programlisting language="myxml"><object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="TargetType" value="Whatever.MyClassFactory, MyAssembly"/>
|
|
<property name="TargetMethod" value="GetInstance"/>
|
|
|
|
<!-- the ordering of arguments is significant -->
|
|
<property name="Arguments">
|
|
<list>
|
|
<value>1st</value>
|
|
<value>2nd</value>
|
|
<value>and 3rd arguments</value>
|
|
<!-- automatic Type-conversion will be performed prior to invoking the method -->
|
|
</list>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<para>The second way involves passing an arguments dictionary to the
|
|
<methodname>NamedArguments</methodname> property... this dictionary
|
|
maps argument names (<literal>String</literal>s) to argument values
|
|
(any object). The argument names are not case-sensitive, and order is
|
|
(obviously) not significant (since dictionaries by definition do not
|
|
have an order). This is shown in the example below <programlisting
|
|
language="myxml"><object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="TargetObject">
|
|
<object type="Whatever.MyClassFactory, MyAssembly"/>
|
|
</property>
|
|
<property name="TargetMethod" value="Execute"/>
|
|
|
|
<!-- the ordering of named arguments is not significant -->
|
|
<property name="NamedArguments">
|
|
<dictionary>
|
|
<entry key="argumentName"><value>1st</value></entry>
|
|
<entry key="finalArgumentName"><value>and 3rd arguments</value></entry>
|
|
<entry key="anotherArgumentName"><value>2nd</value></entry>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<para>The following example shows how use
|
|
<literal>MethodInvokingFactoryObject</literal> to call an instance
|
|
method.<programlisting language="myxml"><object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />
|
|
|
|
<object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="myMethodObject"/>
|
|
<property name="TargetMethod" value="Execute"/>
|
|
</object></programlisting> The above example could also have been
|
|
written using an anonymous inner object definition... if the object on
|
|
which the method is to be invoked is not going to be used outside of
|
|
the factory object definition, then this is the preferred idiom
|
|
because it limits the scope of the object on which the method is to be
|
|
invoked to the surrounding factory object.</para>
|
|
|
|
<para>Finally, if you want to use
|
|
<literal>MethodInvokingFactoryObject</literal> in conjunction with a
|
|
method that has a variable length argument list, then please note that
|
|
the variable arguments need to be passed (and configured) as a
|
|
<emphasis>list</emphasis>. Let us consider the following method
|
|
definition that uses the <literal>params</literal> keyword (in C#),
|
|
and its attendant (XML) configuration... <programlisting
|
|
language="csharp">[C#]
|
|
public class MyClassFactory
|
|
{
|
|
public object CreateObject(Type objectType, params string[] arguments)
|
|
{
|
|
return ... // implementation elided for clarity...
|
|
}
|
|
}</programlisting> <programlisting language="myxml"><object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />
|
|
|
|
<object id="paramsMethodObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
|
|
<property name="TargetObject" ref="myMethodObject"/>
|
|
<property name="TargetMethod" value="CreateObject"/>
|
|
<property name="Arguments">
|
|
<list>
|
|
<value>System.String</value>
|
|
<!-- here is the 'params string[] arguments' -->
|
|
<list>
|
|
<value>1st</value>
|
|
<value>2nd</value>
|
|
</list>
|
|
</list>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-objectfactories">
|
|
<title>Provided IFactoryObject implementations</title>
|
|
|
|
<para>In addition to <literal>PropertyRetrievingFactoryObject</literal>,
|
|
<literal>MethodInvokingFactoryObject</literal>, and
|
|
<literal>FieldRetrievingFactoryObject </literal> Spring.NET comes with
|
|
other useful implementations of the <literal>IFactoryObject</literal>
|
|
interface. These are discussed below.</para>
|
|
|
|
<sect3 xml:id="objects-objectfactories-log4net">
|
|
<title>Common logging</title>
|
|
|
|
<para>The <literal>LogFactoryObject</literal> is useful when you would
|
|
like to share a Common.Logging log object across a number of classes
|
|
instead of creating a logging instance per class or class hierarchy.
|
|
Information on the Common.Logging project can be found <link
|
|
ns6:href="http://netcommon.sourceforge.net/">here</link>. In the
|
|
example shown below the same logging instance, with a logging category
|
|
name of "DAOLogger", is used in both the SimpleAccountDao and
|
|
SimpleProductDao data access objects. <programlisting
|
|
language="myxml"><objects xmlns="http://www.springframework.net"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.springframework.net
|
|
http://www.springframework.net/xsd/spring-objects.xsd" >
|
|
|
|
<object name="daoLogger" type="Spring.Objects.Factory.Config.LogFactoryObject, Spring.Core">
|
|
<property name="logName" value="DAOLogger"/>
|
|
</object>
|
|
|
|
<object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp ">
|
|
<property name="maxResults" value="100"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
<property name="log" ref="daoLogger"/>
|
|
</object>
|
|
|
|
<object name="accountDao" type="PropPlayApp.SimpleAccountDao, PropPlayApp ">
|
|
<property name="maxResults" value="100"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
<property name="log" ref="daoLogger"/>
|
|
</object>
|
|
|
|
<object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data">
|
|
<property name="connectionstring" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/>
|
|
</object>
|
|
|
|
</objects></programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="objects-factory-scopes">
|
|
<title>Object Scopes</title>
|
|
|
|
<para>When you create 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"><object id="accountService" type="MyApp.DefaultAccountService, MyApp"/>
|
|
|
|
<!-- the following is equivalent, though redundant (singleton scope is the default) -->
|
|
<object id="accountService" type="MyApp.DefaultAccountService, MyApp" singleton="true"/>
|
|
|
|
|
|
</programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-factory-scopes-prototype">
|
|
<title>The prototype scope</title>
|
|
|
|
<para>The non-singleton, prototype scope of object deployment results in
|
|
the creation of a <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"><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary" scope="prototype"/></programlisting>
|
|
|
|
<note>
|
|
<para>The <literal><singleton/></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"><object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests">
|
|
<property name="name" value="Rod"/>
|
|
<property name="FileMode" value="Create"/>
|
|
</object></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-type-conversion-builtin">
|
|
<title>Built-in TypeConverters</title>
|
|
|
|
<para>Spring.NET pre-registers a number of custom
|
|
<literal>TypeConverter</literal> instances (for example, to convert a
|
|
type expressed as a string into a real <literal>System.Type</literal>
|
|
object). Each of those is listed below and they are all located in the
|
|
<literal>Spring.Objects.TypeConverters</literal> namespace of the
|
|
<literal>Spring.Core</literal> library.</para>
|
|
|
|
<para><table frame="all">
|
|
<title>Built-in <literal>TypeConverters</literal></title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="3*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Type</entry>
|
|
|
|
<entry>Explanation</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><literal>RuntimeTypeConverter</literal></entry>
|
|
|
|
<entry>Parses strings representing
|
|
<literal>System.Types</literal> to actual
|
|
<literal>System.Types</literal> and the other way
|
|
around.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>FileInfoConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving strings to a
|
|
<literal>System.IO.FileInfo</literal> object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>StringArrayConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a comma-delimited list of strings
|
|
to a string-array and vice versa.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>UriConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string representation of a Uri
|
|
to an actual <literal>Uri</literal>-object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>CredentialConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string representation of a
|
|
credential for Web client authentication into an instance of
|
|
<literal>System.Net.ICredentials</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>StreamConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving Spring IResource Uri (string) to
|
|
its corresponding
|
|
<literal>InputStream</literal>-object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>ResourceConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving Spring IResource Uri (string) to
|
|
an <literal>IResource</literal> object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>ResourceManagerConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a two part string (resource name,
|
|
assembly name) to a
|
|
<literal>System.Resources.ResourceManager</literal>
|
|
object.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>RgbColorConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a comma separated list of Red,
|
|
Green, Blue integer values to a
|
|
<literal>System.Drawing.Color</literal> structure.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>ExpressionConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string into an instance of an
|
|
object that implements the <literal>IExpression</literal>
|
|
interface.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>NameValueConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving an XML formatted string to a
|
|
<literal>Specialized.NameValueCollection</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>RegexConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string into an instance of
|
|
<literal>Regex</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>RegistryKeyConverter</literal></entry>
|
|
|
|
<entry>Capable of resolving a string into a
|
|
<literal>Microsoft.Win32.RegistryKey</literal> object.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
|
|
<para>Spring.NET uses the standard .NET mechanisms for the resolution of
|
|
<literal>System.Types</literal>, including, but not limited to checking
|
|
any configuration files associated with your application, checking the
|
|
Global Assembly Cache (GAC), and assembly probing.</para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-type-conversion-custom-overview">
|
|
<title>Custom Type Conversion</title>
|
|
|
|
<para>There are a few ways to register custom type converters. The
|
|
fundamental storage area in Spring for custom type converters is the
|
|
<literal>TypeConverterRegistry</literal> class. The <emphasis>most
|
|
convenient way</emphasis> if using an XML based implementation of
|
|
<literal>IObjectFactory</literal> or
|
|
<literal>IApplicationContext</literal> is to use the custom
|
|
configuration section handler
|
|
<literal>TypeConverterSectionHandler</literal> This is demonstrated in
|
|
section <xref linkend="context-configuration" /></para>
|
|
|
|
<para>An alternate approach, present for legacy reasons in the port of
|
|
Spring.NET from the Java code base, is to use the object factory
|
|
post-processor
|
|
<literal>Spring.Objects.Factory.Config.CustomConverterConfigurer</literal>.
|
|
This is described in the next section.</para>
|
|
|
|
<para>If you are constructing your IoC container Programatically then
|
|
you should use the <literal>RegisterCustomConverter(Type requiredType,
|
|
TypeConverter converter)</literal> method of the
|
|
<literal>ConfigurableObjectFactory</literal> interface.</para>
|
|
|
|
<sect3 xml:id="objects-type-conversion-customconverter">
|
|
<title>Using CustomConverterConfigurer</title>
|
|
|
|
<para>This section shows in detail how to define a custom type
|
|
converter that does not use the .NET <literal>TypeConverter</literal>
|
|
attribute. The type converter class is standalone and inherits from
|
|
the <literal>TypeConverter</literal> class. It uses the legacy factory
|
|
post-processor approach.</para>
|
|
|
|
<para>Consider a user class <emphasis>ExoticType</emphasis>, and
|
|
another class <emphasis>DependsOnExoticType</emphasis> which needs
|
|
ExoticType set as a property:<programlisting language="csharp">public class ExoticType
|
|
{
|
|
private string name;
|
|
|
|
public ExoticType(string name)
|
|
{
|
|
this.name = name;
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get { return this.name; }
|
|
}
|
|
}</programlisting> and <programlisting language="csharp">public class DependsOnExoticType
|
|
{
|
|
public DependsOnExoticType() {}
|
|
|
|
private ExoticType exoticType;
|
|
|
|
public ExoticType ExoticType
|
|
{
|
|
get { return this.exoticType; }
|
|
set { this.exoticType = value; }
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return exoticType.Name;
|
|
}
|
|
}</programlisting> When things are properly set up, we want to be able to
|
|
assign the type property as a string, which a TypeConverter will
|
|
convert into a real ExoticType object behind the scenes:
|
|
<programlisting language="myxml"><object name="sample" type="SimpleApp.DependsOnExoticType, SimpleApp">
|
|
<property name="exoticType" value="aNameForExoticType"/>
|
|
</object></programlisting> The TypeConverter looks like this:
|
|
<programlisting language="csharp">public class ExoticTypeConverter : TypeConverter
|
|
{
|
|
public ExoticTypeConverter()
|
|
{
|
|
}
|
|
|
|
public override bool CanConvertFrom (
|
|
ITypeDescriptorContext context,
|
|
Type sourceType)
|
|
{
|
|
if (sourceType == typeof (string))
|
|
{
|
|
return true;
|
|
}
|
|
return base.CanConvertFrom (context, sourceType);
|
|
}
|
|
|
|
public override object ConvertFrom (
|
|
ITypeDescriptorContext context,
|
|
CultureInfo culture, object value)
|
|
{
|
|
string s = value as string;
|
|
if (s != null)
|
|
{
|
|
return new ExoticType(s.ToUpper());
|
|
}
|
|
return base.ConvertFrom (context, culture, value);
|
|
}
|
|
}</programlisting> Finally, we use the
|
|
<literal>CustomConverterConfigurer</literal> to register the new
|
|
<literal>TypeConverter</literal> with the
|
|
<literal>IApplicationContext</literal>, which will then be able to use
|
|
it as needed: <programlisting language="myxml"><object id="customConverterConfigurer"
|
|
type="Spring.Objects.Factory.Config.CustomConverterConfigurer, Spring.Core">
|
|
<property name="CustomConverters">
|
|
<dictionary>
|
|
<entry key="SimpleApp.ExoticType">
|
|
<object type="SimpleApp.ExoticTypeConverter"/>
|
|
</entry>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="objects-factory-nature">
|
|
<title>Customizing the nature of an object</title>
|
|
|
|
<sect2 xml:id="objects-factory-lifecycle">
|
|
<title>Lifecycle interfaces</title>
|
|
|
|
<para>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"><object id="exampleInitObject" type="Examples.ExampleObject" init-method="init"/></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"><object id="exampleInitObject" type="Examples.AnotherExampleObject"/></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"><object id="exampleInitObject" type="Examples.AnotherExampleObject" /></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"><object id="inheritedTestObject" type="Spring.Objects.TestObject, Spring.Core.Tests" abstract="true">
|
|
<property name="name" value="parent"/>
|
|
<property name="age" value="1"/>
|
|
</object>
|
|
<object id="inheritsWithDifferentClass" type="Spring.Objects.DerivedTestObject, Spring.Core.Tests"
|
|
parent="inheritedTestObject" init-method="Initialize">
|
|
<property name="name" value="override"/>
|
|
<!-- age will inherit value of 1 from parent -->
|
|
</object></programlisting></para>
|
|
|
|
<para>A child object definition 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"><object id="inheritedTestObjectWithoutClass" abstract="true">
|
|
<property name="name" value="parent"/>
|
|
<property name="age" value="1"/>
|
|
</object>
|
|
<object id="inheritsWithClass" type="Spring.Objects.DerivedTestObject, Spring.Core.Tests"
|
|
parent="inheritedTestObjectWithoutClass" init-method="Initialize">
|
|
<property name="name" value="override"/>
|
|
<!-- age will inherit value of 1 from parent -->
|
|
</object></programlisting></para>
|
|
|
|
<para>The parent object cannot be instantiated on its own since it
|
|
incomplete, and it is also explicitly marked as abstract. When a
|
|
definition is 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"><object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/>
|
|
<object id="anotherObject" type="Examples.ExampleObject, ExamplesLibrary" singleton="false"/></programlisting>
|
|
<programlisting language="csharp">[C#]
|
|
object one = factory ["exampleObject"]; // gets the object defined as 'exampleObject'
|
|
object two = factory ["exampleObject"];
|
|
Console.WriteLine (one == two) // prints 'true'
|
|
object three = factory ["anotherObject"]; // gets the object defined as 'anotherObject'
|
|
object four = factory ["anotherObject"];
|
|
Console.WriteLine (three == four); // prints 'false'
|
|
</programlisting></para>
|
|
|
|
<para>The client-side view of the <literal>IObjectFactory</literal> is
|
|
surprisingly simple. The <literal>IObjectFactory</literal> interface has
|
|
only seven methods (and the aforementioned indexer) for clients to call:
|
|
<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>bool ContainsObject(string)</literal>: returns true
|
|
if the <literal>IObjectFactory</literal> contains an object
|
|
definition that matches the given name.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>object GetObject(string)</literal>: returns an
|
|
instance of the object registered under the given name. Depending on
|
|
how the object was configured by the
|
|
<literal>IObjectFactory</literal> configuration, either a singleton
|
|
(and thus shared) instance or a newly created object will be
|
|
returned. An <literal>ObjectsException</literal> will be thrown when
|
|
either the object could not be found (in which case it'll be a
|
|
<literal>NoSuchObjectDefinitionException</literal>), or an exception
|
|
occurred while instantiated and preparing the object.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Object this [string]</literal>: this is the indexer
|
|
for the <literal>IObjectFactory</literal> interface. It functions in
|
|
all other respects in exactly the same way as the
|
|
<literal>GetObject(string)</literal> method. The rest of this
|
|
documentation will always refer to the
|
|
<literal>GetObject(string)</literal> method, but be aware that you
|
|
can use the indexer anywhere that you can use the
|
|
<literal>GetObject(string)</literal> method.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Object GetObject(string, Type)</literal>: returns an
|
|
object, registered under the given name. The object returned will be
|
|
cast to the given <literal>Type</literal>. If the object could not
|
|
be cast, corresponding exceptions will be thrown
|
|
(<literal>ObjectNotOfRequiredTypeException</literal>). Furthermore,
|
|
all rules of the <literal>GetObject(string)</literal> method apply
|
|
(see above).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>bool IsSingleton(string)</literal>: determines
|
|
whether or not the object definition registered under the given name
|
|
is a singleton or a prototype. If the object definition
|
|
corresponding to the given name could not be found, an exception
|
|
will be thrown
|
|
(<literal>NoSuchObjectDefinitionException</literal>)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string[] GetAliases(string)</literal>: returns the
|
|
aliases for the given object name, if any were defined in the
|
|
<literal>IObjectDefinition</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void ConfigureObject(object target, 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>&</literal> when calling the
|
|
<methodname>GetObject</methodname> method of the
|
|
<literal>IObjectFactory</literal> and
|
|
<literal>IApplicationContext</literal> interfaces. So for a given
|
|
<literal>IFactoryObject</literal> with an id
|
|
<literal>myObject</literal>, invoking
|
|
<literal>GetObject("myObject")</literal> on the
|
|
<literal>IObjectFactory</literal> will return the product of the
|
|
<literal>IFactoryObject</literal>, but invoking
|
|
<literal>GetObject("&myObject")</literal> will return the
|
|
<literal>IFactoryObject</literal> instance itself.</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Container extension points</title>
|
|
|
|
<para>The IoC component of the Spring Framework has been designed for
|
|
extension. There is typically no need for an application developer to
|
|
subclass any of the various <literal>IObjectFactory</literal> or
|
|
<literal>IApplicationContext</literal> implementation classes. The Spring
|
|
IoC container can be infinitely extended by plugging in implementations of
|
|
special integration interfaces. The next few sections are devoted to
|
|
detailing all of these various integration interfaces.</para>
|
|
|
|
<sect2 xml:id="objects-factory-customizing">
|
|
<title>Customizing objects with
|
|
<literal>IObjectPostProcessors</literal></title>
|
|
|
|
<para>The first extension point that we will look at is the
|
|
<literal>Spring.Objects.Factory.Config.IObjectPostProcessor</literal>
|
|
interface. This interface defines a number of callback methods that you
|
|
as an application developer can implement in order to provide your own
|
|
(or override the containers default) instantiation logic,
|
|
dependency-resolution logic, and so forth. If you want to do some custom
|
|
logic after the Spring container has finished instantiating, configuring
|
|
and otherwise initializing an object, you can plug in one or more
|
|
<literal>IObjectPostProcessor</literal> implementations.</para>
|
|
|
|
<para>You can configure multiple
|
|
<literal>IObjectPostProcessors</literal> if you wish. You can control
|
|
the order in which these <literal>IObjectPostProcessor</literal> execute
|
|
by setting the 'Order' property (you can only set this property if the
|
|
<literal>IObjectPostProcessor</literal> implements the
|
|
<literal>IOrdered</literal> interface; if you write your own
|
|
<literal>IObjectPostProcessor</literal> you should consider implementing
|
|
the <literal>IOrdered</literal> interface too); consult the SDK docs for
|
|
the <literal>IObjectPostProcessor</literal> and
|
|
<literal>IOrdered</literal> interfaces for more details.</para>
|
|
|
|
<note>
|
|
<para><literal>IObjectPostProcessor</literal> operate on object
|
|
instances; that is to say, the Spring IoC container will have
|
|
instantiated a object instance for you, and then
|
|
<literal>IObjectPostProcessors</literal> get a chance to do their
|
|
stuff. If you want to change the actual object definition (that is the
|
|
recipe that defines the object), then you rather need to use a
|
|
<literal>IObjectFactoryPostProcessor</literal> (described below in the
|
|
section entitled <link
|
|
linkend="objects-factory-customizing-factory-postprocessors">Customizing
|
|
configuration metadata with
|
|
IObjectFactoryPostProcessors.</link></para>
|
|
|
|
<para>Also, <literal>IObjectPostProcessors</literal> are scoped
|
|
per-container. This is only relevant if you are using container
|
|
hierarchies. If you define a <literal>IObjectPostProcessor</literal>
|
|
in one container, it will only do its stuff on the objects in that
|
|
container. Objects that are defined in another container will not be
|
|
post-processed by <literal>IObjectPostProcessors</literal> in another
|
|
container, even if both containers are part of the same
|
|
hierarchy.</para>
|
|
</note>
|
|
|
|
<para>The
|
|
<literal>Spring.Objects.Factory.Config.IObjectPostProcessor</literal>
|
|
interface, which consists of two callback methods shown below.
|
|
<programlisting language="csharp">object PostProcessBeforeInitialization(object instance, string name);
|
|
|
|
object PostProcessAfterInitialization(object instance, string name);</programlisting>When
|
|
such a class is registered as a post-processor with the container, for
|
|
each object instance that is created by the container,(see below for how
|
|
this registration is effected), for each object instance that is created
|
|
by the container, the post-processor will get a callback from the
|
|
container both <emphasis>before</emphasis> any initialization methods
|
|
(such as the <methodname>AfterPropertiesSet</methodname> method of the
|
|
<literal>IInitializingObject</literal> interface and any declared init
|
|
method) are called, and also afterwards. The post-processor is free to
|
|
do what it wishes with the object, including ignoring the callback
|
|
completely. An object post-processor will typically check for marker
|
|
interfaces, or do something such as wrap an object with a proxy. Some
|
|
Spring.NET AOP infrastructure classes are implemented as object
|
|
post-processors as they do this proxy-wrapping logic.</para>
|
|
|
|
<para>Other extensions to the <literal>IObjectPostProcessors</literal>
|
|
interface are <literal>IInstantiationAwareObjectPostProcessor</literal>
|
|
and <literal>IDestructionAwareObjectPostProcessor</literal> defined
|
|
below <programlisting language="csharp">public interface IInstantiationAwareObjectPostProcessor : IObjectPostProcessor
|
|
{
|
|
object PostProcessBeforeInstantiation(Type objectType, string objectName);
|
|
|
|
bool PostProcessAfterInstantiation(object objectInstance, string objectName);
|
|
|
|
IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, PropertyInfo[] pis, object objectInstance, string objectName);
|
|
}
|
|
|
|
public interface IDestructionAwareObjectPostProcessor : IObjectPostProcessor
|
|
{
|
|
void PostProcessBeforeDestruction (object instance, string name);
|
|
}</programlisting> The <literal>PostProcessBeforeInstantiation</literal>
|
|
callback method is called right before the container creates the object.
|
|
If the object returned by this method is not null then the default
|
|
instantiation behavior of the container is short circuited. The returned
|
|
object is the one registered with the container and no other
|
|
<literal>IObjectPostProcessor</literal> callbacks will be invoked on it.
|
|
This mechanism is useful if you would like to expose a proxy to the
|
|
object instead of the actual target object. The
|
|
<literal>PostProcessAfterInstantiation</literal> callback method is
|
|
called after the object has been instantiated but before Spring performs
|
|
property population based on explicit properties or autowiring. A return
|
|
value of false would short circuit the standard Spring based property
|
|
population. The callback method
|
|
<literal>PostProcessPropertyValues</literal> is called after Spring
|
|
collects all the property values to apply to the object, but before they
|
|
are applied. This gives you the opportunity to perform additional
|
|
processing such as making sure that a property is set to a value if it
|
|
contains a <literal>[Required]</literal> attribute or to perform
|
|
attribute based wiring, i.e. adding the attribute
|
|
<literal>[Inject("objectName")]</literal> on a property. Both of these
|
|
features are scheduled to be included in Spring .12.</para>
|
|
|
|
<para>The <literal>IDestructionAwareObjectPostProcessor</literal>
|
|
callback contains a single method,
|
|
<literal>PostProcessBeforeDestruction</literal>, which is called before
|
|
a singleton's destroy method is invoked.</para>
|
|
|
|
<para>It is important to know that the <literal>IObjectFactory</literal>
|
|
treats object post-processors slightly differently than the
|
|
<literal>IApplicationContext</literal>. An
|
|
<literal>IApplicationContext</literal> will automatically detect any
|
|
objects which are deployed into it that implement the
|
|
<literal>IObjectPostProcessor</literal> interface, and register them as
|
|
post-processors, to be then called appropriately by the factory on
|
|
object creation. Nothing else needs to be done other than deploying the
|
|
post-processor in a similar fashion to any other object. On the other
|
|
hand, when using plain <literal>IObjectFactories</literal>, object
|
|
post-processors have to manually be explicitly registered, with a code
|
|
sequence such as... <programlisting language="csharp">ConfigurableObjectFactory factory = new .....; // create an IObjectFactory
|
|
... // now register some objects
|
|
// now register any needed IObjectPostProcessors
|
|
MyObjectPostProcessor pp = new MyObjectPostProcessor();
|
|
factory.AddObjectPostProcessor(pp);
|
|
// now start using the factory
|
|
...</programlisting></para>
|
|
|
|
<para>This explicit registration step is not convenient, and this is one
|
|
of the reasons why the various <literal>IApplicationContext</literal>
|
|
implementations are preferred above plain
|
|
<literal>IObjectFactory</literal> implementations in the vast majority
|
|
of Spring-backed applications, especially when using
|
|
IObjectPostProcessors.</para>
|
|
|
|
<note>
|
|
<para>IObjectPostProcessors and AOP auto-proxying</para>
|
|
|
|
<para>Classes that implement the
|
|
<literal>IObjectPostProcessor</literal> interface are special, and so
|
|
they are treated differently by the container. All
|
|
<literal>IObjectPostProcessors</literal> and their directly referenced
|
|
object will be instantiated on startup, as part of the special startup
|
|
phase of the IApplicationContext, then all those
|
|
<literal>IObjectPostProcessors</literal> will be registered in a
|
|
sorted fashion - and applied to all further objects. Since AOP
|
|
auto-proxying is implemented as a
|
|
<literal>IObjectPostProcessor</literal> itself, no
|
|
<literal>IObjectPostProcessors</literal> or directly referenced
|
|
objects are eligible for auto-proxying (and thus will not have aspects
|
|
'woven' into them). For any such object, you should see an info log
|
|
message: “Object 'foo' is not eligible for getting processed by all
|
|
<literal>IObjectPostProcessors</literal> (for example: not eligible
|
|
for auto-proxying)”.</para>
|
|
</note>
|
|
|
|
<para></para>
|
|
|
|
<sect3 xml:id="object-factory-extension-opp-examples-hw">
|
|
<title>Example: Hello World, IObjectPostProcessor-style</title>
|
|
|
|
<para>This first example is hardly compelling, but serves to
|
|
illustrate basic usage. All we are going to do is code a custom
|
|
IObjectPostProcessor implementation that simply invokes the ToString()
|
|
method of each object as it is created by the container and prints the
|
|
resulting string to the system console. Yes, it is not hugely useful,
|
|
but serves to get the basic concepts across before we move into the
|
|
second example which is actually useful. The basis of the example is
|
|
the MovieFinder quickstart that is included with the Spring.NET
|
|
distribution.</para>
|
|
|
|
<para>Find below the custom IObjectPostProcessor implementation class
|
|
definition</para>
|
|
|
|
<para><programlisting language="csharp">using System;
|
|
using Spring.Objects.Factory.Config;
|
|
|
|
namespace Spring.IocQuickStart.MovieFinder
|
|
{
|
|
public class TracingObjectPostProcessor : IObjectPostProcessor
|
|
{
|
|
public object PostProcessBeforeInitialization(object instance, string name)
|
|
{
|
|
return instance;
|
|
}
|
|
|
|
public object PostProcessAfterInitialization(object instance, string name)
|
|
{
|
|
Console.WriteLine("Object '" + name + "' created : " + instance.ToString());
|
|
return instance;
|
|
}
|
|
}
|
|
}</programlisting>And the following configuration</para>
|
|
|
|
<programlisting language="myxml"><?xml version="1.0" encoding="utf-8" ?>
|
|
<objects xmlns="http://www.springframework.net" >
|
|
<description>An example that demonstrates simple IoC features.</description>
|
|
|
|
<object id="MyMovieLister"
|
|
type="Spring.IocQuickStart.MovieFinder.MovieLister, Spring.IocQuickStart.MovieFinder">
|
|
<property name="movieFinder" ref="MyMovieFinder"/>
|
|
</object>
|
|
|
|
<object id="MyMovieFinder"
|
|
type="Spring.IocQuickStart.MovieFinder.SimpleMovieFinder, Spring.IocQuickStart.MovieFinder"/>
|
|
|
|
<!-- when the above objects are instantiated, this custom IObjectPostProcessor implementation
|
|
will output the fact to the system console -->
|
|
<object type="Spring.IocQuickStart.MovieFinder.TracingObjectPostProcessor, Spring.IocQuickStart.MovieFinder"/>
|
|
</objects></programlisting>
|
|
|
|
<para>Notice how the TracingObjectPostProcessor is simply defined; it
|
|
doesn't even have a name, and because it is a object it can be
|
|
dependency injected just like any other object.</para>
|
|
|
|
<para>Find below a small driver script to exercise the above code and
|
|
configuration;</para>
|
|
|
|
<para><programlisting language="csharp">IApplicationContext ctx =
|
|
new XmlApplicationContext(
|
|
"assembly://Spring.IocQuickStart.MovieFinder/Spring.IocQuickStart.MovieFinder/AppContext.xml");
|
|
|
|
MovieLister lister = (MovieLister) ctx.GetObject("MyMovieLister");
|
|
Movie[] movies = lister.MoviesDirectedBy("Roberto Benigni");
|
|
LOG.Debug("Searching for movie...");
|
|
foreach (Movie movie in movies)
|
|
{
|
|
LOG.Debug(string.Format("Movie Title = '{0}', Director = '{1}'.", movie.Title, movie.Director));
|
|
}
|
|
LOG.Debug("MovieApp Done.");</programlisting>The output of executing the above
|
|
program will be:</para>
|
|
|
|
<programlisting>INFO - Object 'Spring.IocQuickStart.MovieFinder.TracingObjectPostProcessor' is not eligible for being processed by all IObjectPostProcessors
|
|
(for example: not eligible for auto-proxying).
|
|
Object 'MyMovieFinder' created : Spring.IocQuickStart.MovieFinder.SimpleMovieFinder
|
|
Object 'MyMovieLister' created : Spring.IocQuickStart.MovieFinder.MovieLister
|
|
DEBUG - Searching for movie...
|
|
DEBUG - Movie Title = 'La vita e bella', Director = 'Roberto Benigni'.
|
|
DEBUG - MovieApp Done.</programlisting>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="object-factory-extension-opp-examplesrapp">
|
|
<title>Example: the RequiredAttributeObjectPostProcessor</title>
|
|
|
|
<para>Using callback interfaces or annotations in conjunction with a
|
|
custom IObjectPostProcessor implementation is a common means of
|
|
extending the Spring IoC container. The <literal>[Required]</literal>
|
|
attribute in the <literal>Spring.Objects.Factory.Attributes</literal>
|
|
namespace can be used to <emphasis>mark</emphasis> a property as
|
|
being<emphasis> 'required-to-be-set' </emphasis>(i.e. an setter
|
|
property with this attribute applied must be configured to be
|
|
dependency injected with a value), else an
|
|
<literal>ObjectInitializationException</literal> will be thrown by the
|
|
container at runtime.</para>
|
|
|
|
<para>The best way to illustrate the usage of this attribute is with
|
|
an example.</para>
|
|
|
|
<programlisting language="csharp">public class MovieLister
|
|
{
|
|
// the MovieLister has a dependency on the MovieFinder
|
|
private IMovieFinder _movieFinder;
|
|
|
|
// a setter property so that the Spring container can 'inject' a MovieFinder
|
|
[Required]
|
|
public IMovieFinder MovieFinder
|
|
{
|
|
set { _movieFinder = value; }
|
|
}
|
|
|
|
// business logic that actually 'uses' the injected MovieFinder is omitted...
|
|
|
|
}</programlisting>
|
|
|
|
<para>Hopefully the above class definition reads easy on the eye. Any
|
|
and all <literal>IObjectDefinitions</literal> for the
|
|
<literal>MovieLister</literal> class must be provided with a
|
|
value.</para>
|
|
|
|
<para>Let's look at an example of some XML configuraiton that will not
|
|
pass validation.</para>
|
|
|
|
<programlisting language="myxml"><object id="MyMovieLister"
|
|
type="Spring.IocQuickStart.MovieFinder.MovieLister, Spring.IocQuickStart.MovieFinder">
|
|
<!-- whoops, no MovieFinder is set (and this property is [Required]) -->
|
|
</object></programlisting>
|
|
|
|
<para>At runtime the following message will be generated by the Spring
|
|
container</para>
|
|
|
|
<programlisting>Error creating context 'spring.root': Property 'MovieFinder' required for object 'MyMovieLister'</programlisting>
|
|
|
|
<para>There is one last little piece of Spring configuration that is
|
|
required to actually 'switch on' this behavior. Simply annotating the
|
|
'setter' properties of your classes is not enough to get this
|
|
behavior. You need to enable a component that is aware of the
|
|
<literal>[Required]</literal> attribute and that can process it
|
|
appropriately.</para>
|
|
|
|
<para>This component is the
|
|
<literal>RequiredAttributeObjectPostProcessor</literal> class. This is
|
|
a special <literal>IObjectPostProcessor</literal> implementation that
|
|
is <literal>[Required]</literal>-aware and actually provides the 'blow
|
|
up if this required property has not been set' logic. It is very easy
|
|
to configure; simply drop the following object definition into your
|
|
Spring XML configuration.</para>
|
|
|
|
<programlisting language="myxml"><object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"/></programlisting>
|
|
|
|
<para>Finally, one can configure an instance of the
|
|
<literal>RequiredAttributeObjectPostProcessor</literal> class to look
|
|
for another <literal>Attribute</literal> type. This is great if you
|
|
already have your own <literal>[Required]</literal>-style attribute.
|
|
Simply plug it into the definition of a
|
|
<literal>RequiredAttributeObjectPostProcessor</literal> and you are
|
|
good to go. By way of an example, let's suppose you (or your
|
|
organization / team) have defined an attribute called [Mandatory]. You
|
|
can make a <literal>RequiredAttributeObjectPostProcessor</literal>
|
|
instance <literal>[Mandatory]</literal>-aware like so:</para>
|
|
|
|
<programlisting language="myxml"><object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core">
|
|
<property name="RequiredAttributeType" value="MyApp.Attributes.MandatoryAttribute, MyApp"/>
|
|
</object></programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="objects-factory-customizing-factory-postprocessors">
|
|
<title>Customizing configuration metadata with
|
|
<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
|
|
<objects/> element, be sure to mark your various
|
|
<literal>IObjectFactoryPostProcessor</literal> object definitions with
|
|
'lazy-init="false"'.</para>
|
|
</note>
|
|
|
|
<sect3 xml:id="objects-factory-placeholderconfigurer">
|
|
<title>Example: The
|
|
<literal>PropertyPlaceholderConfigurer</literal></title>
|
|
|
|
<para>The <literal>PropertyPlaceholderConfigurer</literal> is an
|
|
excellent solution when you want to externalize a few properties from
|
|
a file containing object definitions. This is useful to allow the
|
|
person deploying an application to customize environment specific
|
|
properties (for example database configuration strings, usernames, and
|
|
passwords), without the complexity or risk of modifying the main XML
|
|
definition file or files for the container.</para>
|
|
|
|
<para>Variable substitution is performed on simple property values,
|
|
lists, dictionaries, sets, constructor values, object type name, and
|
|
object names in runtime object references. Furthermore, placeholder
|
|
values can also cross-reference other placeholders.</para>
|
|
|
|
<para>Note that <literal>IApplicationContext</literal>s are able to
|
|
automatically recognize and apply objects deployed in them that
|
|
implement the <literal>IObjectFactoryPostProcessor</literal>
|
|
interface. This means that as described here, applying a
|
|
<literal>PropertyPlaceholderConfigurer</literal> is much more
|
|
convenient when using an <literal>IApplicationContext</literal>. For
|
|
this reason, it is recommended that users wishing to use this or other
|
|
object factory postprocessors use an
|
|
<literal>IApplicationContext</literal> instead of an
|
|
<literal>IObjectFactory</literal>.</para>
|
|
|
|
<para>In the example below a data access object needs to be configured
|
|
with a database connection and also a value for the maximum number of
|
|
results to return in a query. Instead of hard coding the values into
|
|
the main Spring.NET configuration file we use place holders, in the
|
|
NAnt style of <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"><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
<section name="DaoConfiguration" type="System.Configuration.NameValueSectionHandler"/>
|
|
<section name="DatabaseConfiguration" type="System.Configuration.NameValueSectionHandler"/>
|
|
</configSections>
|
|
|
|
<DaoConfiguration>
|
|
<add key="maxResults" value="1000"/>
|
|
</DaoConfiguration>
|
|
|
|
<DatabaseConfiguration>
|
|
<add key="connection.string" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/>
|
|
</DatabaseConfiguration>
|
|
|
|
<spring>
|
|
<context>
|
|
<resource uri="assembly://DaoApp/DaoApp/objects.xml"/>
|
|
</context>
|
|
</spring>
|
|
|
|
</configuration></programlisting></para>
|
|
|
|
<para>Notice the presence of two <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"><objects xmlns="http://www.springframework.net"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.springframework.net
|
|
http://www.springframework.net/xsd/spring-objects.xsd" >
|
|
|
|
<object name="productDao" type="DaoApp.SimpleProductDao, DaoApp ">
|
|
<property name="maxResults" value="${maxResults}"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
</object>
|
|
|
|
<object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data">
|
|
<property name="connectionstring" value="${connection.string}"/>
|
|
</object>
|
|
|
|
<object name="appConfigPropertyHolder"
|
|
type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
|
|
<property name="configSections">
|
|
<value>DaoConfiguration,DatabaseConfiguration</value>
|
|
</property>
|
|
</object>
|
|
|
|
</objects></programlisting>
|
|
|
|
<para>The values of <literal>${maxResults}</literal> and
|
|
<literal>${connection.string}</literal> match the key names used in
|
|
the two <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"><section name="hibernateConfiguration"
|
|
type="System.Configuration.NameValueFileSectionHandler, System,
|
|
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/></programlisting></para>
|
|
</note>
|
|
|
|
<sect4>
|
|
<title>Type, Ref, and Expression substitution</title>
|
|
|
|
<para>The PropertyPlaceholderConfigurer can be used to substitute
|
|
type names, which is sometimes useful when you have to pick a
|
|
particular implementation class at runtime. For example:</para>
|
|
|
|
<programlisting language="myxml"><object id="MyMovieFinder" type="${custom.moviefinder.type}"/></programlisting>
|
|
|
|
<para>If the class is unable to be resolved at runtime to a valid
|
|
type, resolution of the object will fail once it is about to be
|
|
created (which is during the
|
|
<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"><object id="TestObject" type="Simple.TestObject, MyAssembly">
|
|
<property name="age" expression="${ageExpression}"/>
|
|
<property name="spouse" ref="${spouse-ref}"/>
|
|
</object></programlisting>
|
|
</sect4>
|
|
|
|
<sect4 xml:id="objects-factory-placeholderconfigurer-envvars">
|
|
<title>Replacement with Environment Variables</title>
|
|
|
|
<para>You may also use the value environment variables to replace
|
|
property placeholders. The use of environment variables is
|
|
controlled via the property
|
|
<literal>EnvironmentVariableMode</literal>. This property is an
|
|
enumeration of the type <literal>EnvironmentVariablesMode</literal>
|
|
and has three values, Never, Fallback, and Override.
|
|
<literal>Fallback</literal> is the default value and will resolve a
|
|
property placeholder if it was not already done so via a value from
|
|
a resource location. <literal>Override</literal> will apply
|
|
environment variables before applying values defined from a resource
|
|
location. <literal>Never</literal> will, quite appropriately,
|
|
disable environment variable substitution. An example of how the
|
|
<literal>PropertyPlaceholderConfigurer</literal> XML is modified to
|
|
enable override usage is shown below <programlisting
|
|
language="myxml"><object name="appConfigPropertyHolder"
|
|
type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
|
|
<property name="configSections" value="DaoConfiguration,DatabaseConfiguration"/>
|
|
<property name="EnvironmentVariableMode" value="Override"/>
|
|
</object>
|
|
</objects></programlisting></para>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-factory-overrideconfigurer">
|
|
<title>Example: The
|
|
<literal>PropertyOverrideConfigurer</literal></title>
|
|
|
|
<para>The <literal>PropertyOverrideConfigurer</literal>, another
|
|
object factory post-processor, is similar to the
|
|
<literal>PropertyPlaceholderConfigurer</literal>, but in contrast to
|
|
the latter, the original definitions can have default values or no
|
|
values at all for object properties. If an overriding configuration
|
|
file does not have an entry for a certain object property, the default
|
|
context definition is used.</para>
|
|
|
|
<para>Note that the object factory definition is
|
|
<emphasis>not</emphasis> aware of being overridden, so it is not
|
|
immediately obvious when looking at the XML definition file that the
|
|
override configurer is being used. In case that there are multiple
|
|
<literal>PropertyOverrideConfigurer</literal> instances that define
|
|
different values for the same object property, the last one will win
|
|
(due to the overriding mechanism).</para>
|
|
|
|
<para>The example usage is similar to when using
|
|
<literal>PropertyPlaceHolderConfigurer</literal> except that the key
|
|
name refers to the name given to the object in the Spring.NET
|
|
configuration file and is suffixed via 'dot' notation with the name of
|
|
the property For example, if the application configuration file is
|
|
<programlisting language="myxml"><configuration>
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
<section name="DaoConfigurationOverride" type="System.Configuration.NameValueSectionHandler"/>
|
|
</configSections>
|
|
|
|
<DaoConfigurationOverride>
|
|
<add key="productDao.maxResults" value="1000"/>
|
|
</DaoConfigurationOverride>
|
|
|
|
<spring>
|
|
<context>
|
|
<resource uri="assembly://DaoApp/DaoApp/objects.xml"/>
|
|
</context>
|
|
</spring>
|
|
|
|
</configuration></programlisting> Then the value of 1000 will be used to
|
|
overlay the value of 2000 set in the Spring.NET configuration file
|
|
shown below <programlisting language="myxml"><objects xmlns="http://www.springframework.net"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd" >
|
|
|
|
<object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp " >
|
|
<property name="maxResults" value="2000"/>
|
|
<property name="dbConnection" ref="myConnection"/>
|
|
<property name="log" ref="daoLog"/>
|
|
</object>
|
|
|
|
<object name="daoLog" type="Spring.Objects.Factory.Config.LogFactoryObject, Spring.Core">
|
|
<property name="logName" value="DAOLogger"/>
|
|
</object>
|
|
|
|
<object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data">
|
|
<property name="connectionstring">
|
|
<value>dsn=MyDSN;uid=sa;pwd=myPassword;</value>
|
|
</property>
|
|
</object>
|
|
|
|
<object name="appConfigPropertyOverride" type="Spring.Objects.Factory.Config.PropertyOverrideConfigurer, Spring.Core">
|
|
<property name="configSections">
|
|
<value>DaoConfigurationOverride</value>
|
|
</property>
|
|
</object>
|
|
|
|
</objects></programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="objects-variablesource">
|
|
<title>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"><object type="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core">
|
|
<property name="VariableSources">
|
|
<list>
|
|
<object type="Spring.Objects.Factory.Config.PropertyFileVariableSource, Spring.Core">
|
|
<property name="Location" value="~\application.properties" />
|
|
</object>
|
|
<object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core">
|
|
<property name="SectionNames" value="CryptedConfiguration" />
|
|
</object>
|
|
</list>
|
|
</property>
|
|
</object> </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"><!-- app.config: -->
|
|
<configuration>
|
|
<configSections>
|
|
<section name="DonConfiguration" type="System.Configuration.NameValueSectionHandler"/>
|
|
</configSections>
|
|
<DonConfiguration>
|
|
<add key="don_name" value="Dick Whitman"/>
|
|
<add key="don_age" value="41" />
|
|
</DonConfiguration>
|
|
</configuration>
|
|
|
|
<!-- VariableSource configuration: -->
|
|
<object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core">
|
|
<property name="SectionNames" value="DonConfiguration" />
|
|
</object>
|
|
|
|
<!-- consume variables: -->
|
|
<object type="Example.Person, Spring.IocQuickStart.VariableSources">
|
|
<property name="Name" value="${don_name}" />
|
|
<property name="Age" value="${don_age}" />
|
|
</object>
|
|
</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"><!-- From .net's ApplicationSettings: -->
|
|
<object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core">
|
|
<property name="SectionNames" value="applicationSettings/MyApp.Properties.Settings" />
|
|
</object>
|
|
|
|
<!-- From .net's UserSettings: -->
|
|
<object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core">
|
|
<property name="SectionNames" value="userSettings/MyApp.Properties.Settings" />
|
|
</object>
|
|
</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>&{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><object type="Spring.Objects.Factory.Config.PropertyFileVariableSource, Spring.Core">
|
|
<property name="Location" value="~\application.properties" />
|
|
<property name="IgnoreMissingResources" value="true"/>
|
|
</object></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"><object type="Spring.Objects.Factory.Config.ConfigurableVariableSource, Spring.Core">
|
|
<property name="Variables">
|
|
<name-values>
|
|
<add key="midge_name" value="Midge Daniels"/>
|
|
<add key="midge_age" value="33"/>
|
|
</name-values>
|
|
</property>
|
|
</object></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"><object type="Spring.Objects.Factory.Config.CommandLineArgsVariableSource, Spring.Core">
|
|
<property name="ArgumentPrefix" value ="/" /> <!-- optional; default: "/" -->
|
|
<property name="ValueSeparator" value=":" /> <!-- optional; default: ":" -->
|
|
</object></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"><object type="Spring.Objects.Factory.Config.RegistryVariableSource, Spring.Core">
|
|
<property name="Key" value="HKEY_CURRENT_USER\MyKey" />
|
|
</object></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"><object type="Spring.Objects.Factory.Config.EnvironmentVariableSource, Spring.Core" />
|
|
</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"><object type="Spring.Objects.Factory.Config.ConnectionStringsVariableSource, Spring.Core" /></programlisting>
|
|
|
|
<para>Assuming the following connection strings section in your
|
|
application configuration file:</para>
|
|
|
|
<programlisting language="myxml"><connectionStrings>
|
|
<add name="myConnection"
|
|
connectionString="Data Source=myserver;Integrated Security=True;..."
|
|
providerName="System.Data.SqlClient" />
|
|
</connectionStrings></programlisting>
|
|
|
|
<para>Then you would use the variables as in following object
|
|
definition:</para>
|
|
|
|
<programlisting language="myxml"><object type="Example.MyClass, MyAssembly">
|
|
<property name="ConnectionString" value="${myConnection.connectionString}" />
|
|
<property name="ProviderName" value="${myConnection.providerName}" />
|
|
</object> </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"><object type="Spring.Objects.Factory.Config.SpecialFolderVariableSource, Spring.Core" /></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"><object id="specials" type="Example.Specials, Spring.IocQuickStart.VariableSources">
|
|
<property name="FullPathToDesktop" value="${Desktop}" />
|
|
<property name="FullPathToPrgramFiles" value="${ProgramFiles}" />
|
|
</object></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>&</literal>' (sans quotes) when calling the
|
|
<literal>GetObject</literal> method of the
|
|
<literal>IObjectFactory</literal> (including
|
|
<literal>IApplicationContext</literal>). So for a given
|
|
<literal>IFactoryObject</literal> with an id of
|
|
'<literal>myObject</literal>', invoking
|
|
<literal>GetObject("myObject")</literal> on the container will return
|
|
the product of the <literal>IFactoryObject</literal>, but invoking
|
|
<literal>GetObject("&myObject")</literal> will return the
|
|
<literal>IFactoryObject</literal> instance itself.</para>
|
|
|
|
<sect3>
|
|
<title>IConfigurableFactoryObject</title>
|
|
|
|
<para>The
|
|
<literal>Spring.Objects.Factory.IConfigurableFactoryObject</literal>
|
|
interface inherits from <literal>IFactoryObject</literal> interface
|
|
and adds the following property.<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal> IObjectDefinition ProductTemplate </literal>:
|
|
Gets the template object definition that should be used to
|
|
configure the instance of the object managed by this
|
|
factory.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para><literal>IConfigurableFactoryObject</literal> implementions you
|
|
already have examples of in <xref linkend="client-side" /> are
|
|
<literal>WebServiceProxyFactory</literal>.</para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="context-introduction">
|
|
<title>The <literal>IApplicationContext</literal></title>
|
|
|
|
<para>While the <literal>Spring.Objects</literal> namespace provides basic
|
|
functionality for managing and manipulating objects, often in a
|
|
programmatic way, the <literal>Spring.Context</literal> namespace
|
|
introduces the <literal>IApplicationContext</literal> interface, which
|
|
enhances the functionality provided by the
|
|
<literal>IObjectFactory</literal> interface in a more
|
|
<emphasis>framework-oriented style</emphasis>. Many users will use
|
|
ApplicationContext in a completely declarative fashion, not even having to
|
|
create it manually, but instead relying on support classes such as the
|
|
.NET configuration section handlers such as ContextHandler and
|
|
WebContextHandler together to declaratively define the ApplicationContext
|
|
and retrieve it though a ContextRegistry. (Of course it is still possible
|
|
to create an <literal>IApplicationContext</literal>
|
|
Programatically).</para>
|
|
|
|
<para>The basis for the context module is the
|
|
<literal>IApplicationContext</literal> interface, located in the
|
|
<literal>Spring.Context</literal> namespace. Deriving from the
|
|
<literal>IObjectFactory</literal> interface, it provides all the
|
|
functionality of the <literal>IObjectFactory</literal>. To be able to work
|
|
in a more framework-oriented fashion, using layering and hierarchical
|
|
contexts, the <literal>Spring.Context</literal> namespace also provides
|
|
the following functionality<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><emphasis>Loading of multiple (hierarchical)
|
|
contexts</emphasis>, allowing some of them to be focused and used on
|
|
one particular layer, for example the web layer of an
|
|
application.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Access to localized resources</emphasis> at the
|
|
application level by implementing
|
|
<literal>IMessageSource</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Uniform access to resources</emphasis> that can be
|
|
read in as an InputStream, such as URLs and files by implementing
|
|
<literal>IResourceLoader</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Loosely Coupled Event Propagation</emphasis>.
|
|
Publishers and subscribers of events do not have to be directly
|
|
aware of each other as they register their interest indirectly
|
|
through the application context.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<sect2>
|
|
<title>IObjectFactory or IApplicationContext?</title>
|
|
|
|
<para>Short version: use an
|
|
<emphasis><literal>IApplicationContext</literal></emphasis> unless you
|
|
have a really good reason for not doing so. For those of you that are
|
|
looking for slightly more depth as to the 'but why' of the above
|
|
recommendation, keep reading.</para>
|
|
|
|
<para>As the <literal>IApplicationContext</literal> includes all the
|
|
functionality the object factory via its inheritance of the
|
|
<literal>IObjectFactory</literal> interface, it is generally recommended
|
|
to be used over the <literal>IObjectFactory</literal> except for a few
|
|
limited situations where memory consumption might be critical. This may
|
|
become more important if the .NET Compact Framework is supported. The
|
|
history of <literal>IObjectFactory</literal> comes from the Spring Java
|
|
framework, where the use of Spring in Applets was a concern to reduce
|
|
memory consumption. However, for most 'typical' enterprise applications
|
|
and systems, the <literal>IApplicationContext</literal> is what you will
|
|
want to use. Spring generally makes heavy use of the
|
|
<literal>IObjectPostProcessor</literal> extension point (to effect
|
|
proxying and suchlike), and if you are using just a plain
|
|
<literal>IObjectFactory</literal> then a fair amount of support such as
|
|
transactions and AOP will not take effect (at least not without some
|
|
extra steps on your part), which could be confusing because nothing will
|
|
actually be wrong with the configuration.</para>
|
|
|
|
<para>Find below a feature matrix that lists what features are provided
|
|
by the <literal>IObjectFactory</literal> and
|
|
<literal>IApplicationContext</literal> interfaces (and attendant
|
|
implementations). The following sections describe functionality that
|
|
<literal>IApplicationContext</literal> adds to the basic
|
|
<literal>IObjectFactory</literal> capabilities in a lot more depth than
|
|
the said feature matrix.)</para>
|
|
|
|
<anchor xml:id="context-introduction-ctx-vs-objectfactory-feature-matrix" />
|
|
|
|
<table pgwide="1">
|
|
<title>Feature Matrix</title>
|
|
|
|
<tgroup cols="3">
|
|
<colspec align="left" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry align="center">Feature</entry>
|
|
|
|
<entry align="center"><literal>IObjectFactory</literal></entry>
|
|
|
|
<entry
|
|
align="center"><literal>IApplicationContext</literal></entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><para>Object instantiation/wiring</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Automatic <literal>IObjectPostProcessor</literal>
|
|
registration</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Automatic
|
|
<literal>IObjectFactoryPostProcessor</literal>
|
|
registration</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Convenient <literal>IMessageSource</literal>
|
|
access</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para><literal>ApplicationEvent</literal>
|
|
publication</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>Singleton service locator style access</entry>
|
|
|
|
<entry align="center">No</entry>
|
|
|
|
<entry align="center">Yes</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>Declarative registration of custom resource protocol
|
|
handler, XML Parsers for object definitions, and type
|
|
aliases</entry>
|
|
|
|
<entry align="center">No</entry>
|
|
|
|
<entry align="center">Yes</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="context-configuration">
|
|
<title>Configuration of IApplicationContext</title>
|
|
|
|
<para>Well known locations in the .NET application configuration file are
|
|
used to register resource handlers, custom parsers, type alias, and custom
|
|
type converts in addition to the context and objects sections mentioned
|
|
previously. A sample .NET application configuration file showing all these
|
|
features is shown below. Each section requires the use of a custom
|
|
configuration section handler. Note that the types shown for resource
|
|
handlers and parsers are fictional. <programlisting language="myxml"><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
|
|
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
|
|
<section name="resourceHandlers" type="Spring.Context.Support.ResourceHandlersSectionHandler, Spring.Core"/>
|
|
<section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/>
|
|
<section name="typeConverters" type="Spring.Context.Support.TypeConvertersSectionHandler, Spring.Core"/>
|
|
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
<parsers>
|
|
<parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
|
|
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
|
|
</parsers>
|
|
|
|
<resourceHandlers>
|
|
<handler protocol="db" type="MyCompany.MyApp.Resources.MyDbResource"/>
|
|
</resourceHandlers>
|
|
|
|
<context caseSensitive="false">
|
|
<resource uri="config://spring/objects"/>
|
|
<resource uri="db://user:pass@dbName/MyDefinitionsTable"/>
|
|
</context>
|
|
|
|
<typeAliases>
|
|
<alias name="WebServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web"/>
|
|
<alias name="DefaultPointcutAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/>
|
|
<alias name="AttributePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop"/>
|
|
<alias name="CacheAttribute" type="Spring.Attributes.CacheAttribute, Spring.Core"/>
|
|
<alias name="MyType" type="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/>
|
|
</typeAliases>
|
|
|
|
<typeConverters>
|
|
<converter for="Spring.Expressions.IExpression, Spring.Core" type="Spring.Objects.TypeConverters.ExpressionConverter, Spring.Core"/>
|
|
<converter for="MyTypeAlias" type="MyCompany.MyProject.Converters.MyTypeConverter, MyAssembly"/>
|
|
</typeConverters>
|
|
|
|
<objects xmlns="http://www.springframework.net">
|
|
...
|
|
</objects>
|
|
|
|
</spring>
|
|
|
|
</configuration>
|
|
</programlisting> The new sections are described below. The attribute
|
|
<literal>caseSensitive</literal> allows the for both
|
|
<literal>IObjectFactory</literal> and
|
|
<literal>IApplicationContext</literal> implementations to not pay
|
|
attention to the case of the object names. This is important in web
|
|
applications so that ASP.NET pages can be resolved in a case independent
|
|
manner. The default value is true.</para>
|
|
|
|
<sect2 xml:id="context-custom-parsers">
|
|
<title>Registering custom parsers</title>
|
|
|
|
<para>Instead of using the default XML schema that is generic in nature
|
|
to define an object's properties and dependencies, you can create your
|
|
own XML schema specific to an application domain. This has the benefit
|
|
of being easier to type and getting XML intellisense for the schema
|
|
being used. The downside is that you need to write code that will
|
|
transform this XML into Spring object definitions. One would typically
|
|
implement a custom parser by deriving from the class
|
|
<literal>ObjectsNamespaceParser</literal> and overriding the methods
|
|
<literal> int ParseRootElement(XmlElement root, XmlResourceReader
|
|
reader)</literal> and <literal>int ParseElement(XmlElement element,
|
|
XmlResourceReader reader)</literal>. Registering custom parsers outside
|
|
of App.config will be addressed in a future release.</para>
|
|
|
|
<para>To register a custom parser register a section handler of the type
|
|
<literal>Spring.Context.Support.NamespaceParsersSectionHandler</literal>
|
|
in the configSecitons section of App.config. The parser configuration
|
|
section contains one or more <parser> elements each with a type
|
|
attribute. Below is an example that registers all the namespaces
|
|
provided in Spring.</para>
|
|
|
|
<note>
|
|
<para>As of Spring.NET 1.2.0 it is no longer necessary to explicitly
|
|
configure the namespace parsers that come with Spring via a custom
|
|
section in App.config. You will still need to register custom
|
|
namespace parsers if you are writing your own.</para>
|
|
</note>
|
|
|
|
<programlisting language="myxml"><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<!-- other configuration section handler defined here -->
|
|
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
<parsers>
|
|
<parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
|
|
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
|
|
<parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" />
|
|
<parser type="Spring.Validation.Config.ValidationNamespaceParser, Spring.Core" />
|
|
<parser type="Spring.Remoting.Config.RemotingNamespaceParser, Spring.Services" />
|
|
</parsers>
|
|
</spring>
|
|
|
|
</configuration></programlisting>
|
|
|
|
<para>You can also register custom parser programmatically using the
|
|
NamespaceParserRegistry. Here is an example taken from the code used in
|
|
the Transactions Quickstart application.</para>
|
|
|
|
<programlisting language="csharp">NamespaceParserRegistry.RegisterParser(typeof(DatabaseNamespaceParser));
|
|
NamespaceParserRegistry.RegisterParser(typeof(TxNamespaceParser));
|
|
NamespaceParserRegistry.RegisterParser(typeof(AopNamespaceParser));
|
|
|
|
IApplicationContext context =
|
|
new XmlApplicationContext("assembly://Spring.TxQuickStart.Tests/Spring.TxQuickStart/system-test-local-config.xml");</programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-custom-resourcehandler">
|
|
<title>Registering custom resource handlers</title>
|
|
|
|
<para>Creating a custom resource handler means implementing the
|
|
<literal>IResource</literal> interface. The base class
|
|
<literal>AbstractResource</literal> is a useful starting point. Look at
|
|
the Spring source for classes such as
|
|
<literal>FileSystemResource</literal> or
|
|
<literal>AssemblyResource</literal> for implementation tips. You can
|
|
register your custom resource handler either within App.config, as shown
|
|
in the program listing at the start of this section using a
|
|
.<literal>ResourceHandlersSectionHandler</literal> or define an object
|
|
of the type
|
|
<literal>Spring.Objects.Factory.Config.ResourceHandlerConfigurer</literal>
|
|
as you would any other Spring managed object. An example of the latter
|
|
is shown below:</para>
|
|
|
|
<programlisting language="myxml"><object id="myResourceHandlers" type="Spring.Objects.Factory.Config.ResourceHandlerConfigurer, Spring.Core">
|
|
<property name="ResourceHandlers">
|
|
<dictionary>
|
|
<entry key="db" value="MyCompany.MyApp.Resources.MyDbResource, MyAssembly"/>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-type-alias">
|
|
<title>Registering Type Aliases</title>
|
|
|
|
<para>Type aliases allow you to simplify Spring configuration file by
|
|
replacing fully qualified type name with an alias for frequently used
|
|
types. Aliases can be registered both within a config file and
|
|
programatically and can be used anywhere in the context config file
|
|
where a fully qualified type name is expected. Type aliases can also be
|
|
defined for generic types.</para>
|
|
|
|
<para>One way to configure a type alias is to define them in a custom
|
|
config section in the Web/App.config file for your application, as well
|
|
as the custom configuration section handler. See the previous XML
|
|
configuration listing for an example that makes an alias for the
|
|
WebServiceExporter type. Once you have aliases defined, you can simply
|
|
use them anywhere where you would normally specify a fully qualified
|
|
type name:<programlisting language="myxml"><object id="MyWebService" type="WebServiceExporter">
|
|
...
|
|
</object>
|
|
|
|
<object id="cacheAspect" type="DefaultPointcutAdvisor">
|
|
<property name="Pointcut">
|
|
<object type="AttributePointcut">
|
|
<property name="Attribute" value="CacheAttribute"/>
|
|
</object>
|
|
</property>
|
|
<property name="Advice" ref="aspNetCacheAdvice"/>
|
|
</object></programlisting></para>
|
|
|
|
<para>To register a type alias register a section handler of the type
|
|
<literal>Spring.Context.Support.TypeAliasesSectionHandler</literal> in
|
|
the configSecitons section of App.config. The type alias configuration
|
|
section contains one or more <alias> elements each with a name and
|
|
a type attribute. Below is an example that registers the alias for
|
|
WebServiceExporter</para>
|
|
|
|
<programlisting language="myxml"><configuration>
|
|
|
|
<configSections>
|
|
<sectionGroup name="spring">
|
|
<!-- other configuration section handler defined here -->
|
|
<section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/>
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
<typeAliases>
|
|
<alias name="WebServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web"/>
|
|
</typeAliases>
|
|
</spring>
|
|
|
|
</configuration></programlisting>
|
|
|
|
<para>For an example showing type aliases for generic types see <xref
|
|
linkend="objects-creation-generic-types" />.</para>
|
|
|
|
<para>Another way is to define an object of the type
|
|
<literal>Spring.Objects.Factory.Config.TypeAliasConfigurer</literal>
|
|
within the regular <objects> section of any standard Spring
|
|
configuration file. This approach allows for more modularity in defining
|
|
type aliases, for example if you can't access App.config/Web.config. An
|
|
example of registration using a <literal>TypeAliasConfigurer</literal>
|
|
is shown below</para>
|
|
|
|
<programlisting language="myxml"><object id="myTypeAlias" type="Spring.Objects.Factory.Config.TypeAliasConfigurer, Spring.Core">
|
|
<property name="TypeAliases">
|
|
<dictionary>
|
|
<entry key="WebServiceExporter" value="Spring.Web.Services.WebServiceExporter, Spring.Web"/>
|
|
<entry key="DefaultPointcutAdvisor" value="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/>
|
|
<entry key="MyType" value="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-type-converters">
|
|
<title>Registering Type Converters</title>
|
|
|
|
<para>The standard .NET mechanism for specifying a type converter is to
|
|
add a <literal>TypeConverter</literal> attribute to a type definition to
|
|
specify the type of the Converter. This is the preferred way of defining
|
|
type converters if you control the source code for the type that you
|
|
want to define a converter for. However, this configuration section
|
|
allows you to specify converters for the types that you don't control,
|
|
and it also allows you to override some of the standard type converters,
|
|
such as the ones that are defined for some of the types in the .NET Base
|
|
Class Library.</para>
|
|
|
|
<para>You can specify the type converters in App.config by using
|
|
Spring.Context.Support.TypeConvertersSectionHandler as shown before or
|
|
define an object of the type
|
|
<literal>Spring.Objects.Factory.Config.</literal><literal>CustomConverterConfigurer</literal>.
|
|
An example of registration using a
|
|
<literal>CustomConverterConfigurer</literal> is shown below</para>
|
|
|
|
<programlisting language="myxml"><object id="myTypeConverters" type="Spring.Objects.Factory.Config.CustomConverterConfigurer, Spring.Core">
|
|
<property name="CustomConverters">
|
|
<dictionary>
|
|
<entry key="System.Date" value="MyCompany.MyProject.MyNamespace.MyCustomDateConverter, MyAssembly"/>
|
|
</dictionary>
|
|
</property>
|
|
</object></programlisting>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="context-functionality">
|
|
<title>Added functionality of the
|
|
<literal>IApplicationContext</literal></title>
|
|
|
|
<para>As already stated in the previous section, the
|
|
<literal>IApplicationContext</literal> has a couple of features that
|
|
distinguish it from the <literal>IObjectFactory</literal>. Let us review
|
|
them one-by-one.</para>
|
|
|
|
<sect2 xml:id="context-functionality-hierarchy">
|
|
<title>Context Hierarchies</title>
|
|
|
|
<para>You can structure the configuration information of application
|
|
context into hierarchies that naturally reflect the internal layering of
|
|
your application. As an example, abstract object definitions may appear
|
|
in a parent application context configuration file, possibly as an
|
|
embedded assembly resource so as not to invite accidental changes.
|
|
<programlisting language="myxml"><spring>
|
|
<context>
|
|
<resource uri="assembly://MyAssembly/MyProject/root-objects.xml"/>
|
|
<context name="mySubContext">
|
|
<resource uri="file://objects.xml"/>
|
|
</context>
|
|
</context>
|
|
</spring></programlisting> The nesting of <literal>context</literal>
|
|
elements reflects the parent-child hierarchy you are creating. The
|
|
nesting can be to any level though it is unlikely one would need a deep
|
|
application hierarchy. The xml file must contain the
|
|
<literal><objects></literal> as the root name. Another example of
|
|
a hierarchy, but using sections in the application configuration file is
|
|
shown below. <programlisting language="myxml"><configSections>
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
<sectionGroup name="child">
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
</sectionGroup>
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
|
|
<context name="ParentContext">
|
|
<resource uri="config://spring/objects"/>
|
|
<context name="ChildContext">
|
|
<resource uri="config://spring/child/objects"/>
|
|
</context>
|
|
</context>
|
|
|
|
<objects xmlns="http://www.springframework.net">
|
|
|
|
...
|
|
|
|
</objects>
|
|
|
|
<child>
|
|
<objects xmlns="http://www.springframework.net">
|
|
|
|
...
|
|
|
|
</objects>
|
|
</child>
|
|
|
|
</spring></programlisting></para>
|
|
|
|
<para>As a reminder, the <literal>type</literal> attribute of the
|
|
context tag is optional and defaults to
|
|
<literal>Spring.Context.Support.XmlApplicationContext</literal>. The
|
|
name of the context can be used in conjunction with the service locator
|
|
class, <literal>ContextRegistry</literal>, discussed in <xref
|
|
linkend="objects-servicelocator" /></para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-functionality-messagesource">
|
|
<title>Using <literal>IMessageSource</literal></title>
|
|
|
|
<para>The <literal>IApplicationContext</literal> interface extends an
|
|
interface called <literal>IMessageSource</literal> and provides
|
|
localization (i18n or internationalization) services for text messages
|
|
and other resource data types such as images. This functionality makes
|
|
it easier to use .NET's localization features at an application level
|
|
and also offers some performance enhancements due to caching of
|
|
retrieved resources. Together with the
|
|
<literal>NestingMessageSource</literal>, capable of hierarchical message
|
|
resolving, these are the basic interfaces Spring.NET provides for
|
|
localization. Let's quickly review the methods defined there:
|
|
<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name)</literal>: retrieves
|
|
a message from the <literal>IMessageSource</literal> and using
|
|
CurrentUICulture.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, CultureInfo
|
|
cultureInfo)</literal>: retrieves a message from the
|
|
<literal>IMessageSource</literal> using a specified
|
|
culture.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, params object[]
|
|
args)</literal>: retrieves a message from the
|
|
<literal>IMessageSource</literal> using a variable list of
|
|
arguments as replacement values in the message. The
|
|
CurrentUICulture is used to resolve the message.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, CultureInfo
|
|
cultureInfo, params object[] args)</literal>: retrieves a message
|
|
from the <literal>IMessageSource</literal> using a variable list
|
|
of arguments as replacement values in the message. The specified
|
|
culture is used to resolve the message.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(string name, string
|
|
defaultMessage, CultureInfo culture, params object[]
|
|
arguments)</literal>: retrieves a message from the
|
|
<literal>IMessageSource</literal> using a variable list of
|
|
arguments as replacement values in the message. The specified
|
|
culture is used to resolve the message. If no message can be
|
|
resolved, the default message is used.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>string GetMessage(IMessageSourceResolvable
|
|
resolvable, CultureInfo culture) </literal>: all properties used
|
|
in the methods above are also wrapped in a class - the
|
|
<literal>MessageSourceResolvable</literal>, which you can use in
|
|
this method.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>object GetResourceObject(string name)</literal>:Get
|
|
a localized resource object, i.e. Icon, Image, etc. given the
|
|
resource name. The CurrentUICulture is used to resolve the
|
|
resource object.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>object GetResourceObject(string name, CultureInfo
|
|
cultureInfo)</literal>:Get a localized resource object, i.e. Icon,
|
|
Image, etc. given the resource name. The specified culture is used
|
|
to resolve the resource object.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void ApplyResources(object value, string
|
|
objectName, CultureInfo cultureInfo)</literal>: Uses a
|
|
ComponentResourceManager to apply resources to all object
|
|
properties that have a matching key name. Resource key names are
|
|
of the form objectName.propertyName</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<para>When an <literal>IApplicationContext</literal> gets loaded, it
|
|
automatically searches for an <literal>IMessageSource</literal> object
|
|
defined in the context. The object has to have the name
|
|
<literal>messageSource</literal>. If such an object is found, all calls
|
|
to the methods described above will be delegated to the message source
|
|
that was found. If no message source was found, the
|
|
<literal>IApplicationContext</literal> checks to see if it has a parent
|
|
containing a similar object, with a similar name. If so, it uses that
|
|
object as the <literal>IMessageSource</literal>. If it can't find any
|
|
source for messages, an empty <literal>StaticMessageSource</literal>
|
|
will be instantiated in order to be able to accept calls to the methods
|
|
defined above.</para>
|
|
|
|
<warning>
|
|
<title>Fallback behavior</title>
|
|
|
|
<para>The fallback rules for localized resources seem to have a bug
|
|
that is fixed by applying Service Pack 1 for .NET 1.1. This affects
|
|
the use of IMessageSource.GetMessage methods that specify CultureInfo.
|
|
The core of the issue in the .NET BCL is the method
|
|
ResourceManager.GetObject that accepts CultureInfo.</para>
|
|
</warning>
|
|
|
|
<para>Spring.NET provides two <literal>IMessageSource</literal>
|
|
implementations. These are <literal>ResourceSetMessageSource</literal>
|
|
and <literal>StaticMessageSource</literal>. Both implement
|
|
<literal>IHierarchicalMessageSource</literal> to resolve messages
|
|
hierarchically. The <literal>StaticMessageSource</literal> is hardly
|
|
ever used but provides programmatic ways to add messages to the source.
|
|
The <literal>ResourceSetMessageSource</literal> is more interesting and
|
|
an example is provided for in the distribution and discussed more
|
|
extensively in the <xref linkend="quickstarts" /> section. The
|
|
<literal>ResourceSetMessageSource</literal> is configured by providing a
|
|
list of <literal>ResourceManager</literal>s. When a message code is to
|
|
be resolved, the list of ResourceManagers is searched to resolve the
|
|
code. For each <literal>ResourceManager</literal> a
|
|
<literal>ResourceSet</literal> is retrieved and asked to resolve the
|
|
code. Note that this search does not replace the standard hub-and-spoke
|
|
search for localized resources. The ResourceManagers list specifies the
|
|
multiple 'hubs' where the standard search starts. <programlisting
|
|
language="myxml"><object name="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core">
|
|
<property name="resourceManagers">
|
|
<list>
|
|
<value>Spring.Examples.AppContext.MyResource, Spring.Examples.AppContext</value>
|
|
</list>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<para>You can specify the arguments to construct a ResourceManager as a
|
|
two part string value containing the base name of the resource and the
|
|
assembly name. This will be converted to a ResourceManager via the
|
|
<literal>ResourceManagerConverter</literal> TypeConverter. This
|
|
converter can be similarly used to set a property on any object that is
|
|
of the type <literal>ResourceManager.</literal> You may also specify an
|
|
instance of the <literal>ResourceManager</literal> to use via an object
|
|
reference. The convenience class
|
|
<literal>Spring.Objects.Factory.Config.ResourceManagerFactoryObject</literal>
|
|
can be used to conveniently create an instance of a ResourceManager.
|
|
<programlisting language="myxml"><object name="myResourceManager" type="Spring.Objects.Factory.Config.ResourceManagerFactoryObject, Spring.Core">
|
|
<property name="baseName">
|
|
<value>Spring.Examples.AppContext.MyResource</value>
|
|
</property>
|
|
<property name="assemblyName">
|
|
<value>Spring.Examples.AppContext</value>
|
|
</property>
|
|
</object></programlisting></para>
|
|
|
|
<para>In application code, a call to <literal>GetMessage</literal> will
|
|
retrieve a properly localized message string based on a code value. Any
|
|
arguments present in the retrieved string are replaced using
|
|
<literal>String.Format</literal> semantics. The ResourceManagers,
|
|
ResourceSets and retrieved strings are cached to provide quicker lookup
|
|
performance. The key 'HelloMessage' is contained in the resource file
|
|
with a value of <literal>Hello {0} {1}</literal>. The following call on
|
|
the application context will return the string <literal>Hello Mr.
|
|
Anderson</literal>. <emphasis>Note</emphasis> that the caching of
|
|
ResourceSets is via the concatenation of the ResourceManager base name
|
|
and the CultureInfo string. This combination must be unique.
|
|
<programlisting language="csharp">string msg = ctx.GetMessage("HelloMessage",
|
|
new object[] {"Mr.", "Anderson"},
|
|
CultureInfo.CurrentCulture );
|
|
</programlisting></para>
|
|
|
|
<para>It is possible to chain the resolution of messages by passing
|
|
arguments that are themselves messages to be resolved giving you greater
|
|
flexibility in how you can structure your message resolution. This is
|
|
achieved by passing as an argument a class that implements
|
|
<literal>IMessageResolvable</literal> instead of a string literal. The
|
|
convenience class <literal>DefaultMessageResolvable</literal> is
|
|
available for this purpose. As an example if the resource file contains
|
|
a key name <literal>error.required</literal> that has the value
|
|
'<literal>{0} is required {1}</literal>' and another key name
|
|
<literal>field.firstname</literal> with the value '<literal>First
|
|
name</literal>'. The following code will create the string
|
|
'<literal>First name is required dude!</literal>' <programlisting
|
|
language="csharp">string[] codes = {"field.firstname"};
|
|
DefaultMessageResolvable dmr = new DefaultMessageResolvable(codes, null);
|
|
ctx.GetMessage("error.required",
|
|
new object[] { dmr, "dude!" },
|
|
CultureInfo.CurrentCulture ));
|
|
</programlisting></para>
|
|
|
|
<para>The examples directory in the distribution contains an example
|
|
program, <literal>Spring.Examples.AppContext</literal>, that
|
|
demonstrates usage of these features.</para>
|
|
|
|
<para>The <literal>IMessageSourceAware</literal> interface can also be
|
|
used to acquire a reference to any <literal>IMessageSource</literal>
|
|
that has been defined. Any object that is defined in an
|
|
<literal>IApplicationContext</literal> that implements the
|
|
<literal>IMessageSourceAware</literal> interface will be injected with
|
|
the application context's <literal>IMessageSource</literal> when it (the
|
|
object) is being created and configured.</para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-functionality-resources">
|
|
<title>Using resources within Spring.NET</title>
|
|
|
|
<para>A lot of applications need to access resources. Resources here,
|
|
might mean files, but also news feeds from the Internet or normal web
|
|
pages. Spring.NET provides a clean and transparent way of accessing
|
|
resources in a protocol independent way. The
|
|
<literal>IApplicationContext</literal> has a method
|
|
(<literal>GetResource(string)</literal>) to take care of this. Refer to
|
|
<xref linkend="objects-iresource" /> for more information on the string
|
|
format to use and the <literal>IResource</literal> abstraction in
|
|
general.</para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-functionality-pubsub">
|
|
<title>Loosely coupled events</title>
|
|
|
|
<para>The Eventing Registry allows developers to utilize a loosely
|
|
coupled event wiring mechanism. By decoupling the event publication and
|
|
the event subscription, most of the mundane event wiring is handled by
|
|
the IoC container. Event publishers can publish their event to a central
|
|
registry, either all of their events or a subset based on criteria such
|
|
as delegate type, name, return value, etc... Event subscribers can
|
|
choose to subscribe to any number of published events. Subscribers can
|
|
subscriber to events based on the type of object exposing them, allowing
|
|
one subscriber to handle all events of a certain type without regards to
|
|
how many different instances of that type are created.</para>
|
|
|
|
<para>The <literal>Spring.Objects.Events.IEventRegistry</literal>
|
|
interface represents the central registry and defines publish and
|
|
subscribe methods. <itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>void PublishEvents( object sourceObject
|
|
)</literal>: publishes all events of the source object to
|
|
subscribers that implement the correct handler methods.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void Subscribe(object subscriber )</literal>: The
|
|
subscriber receives all events from the source object for which it
|
|
has matching handler methods.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void Subscribe(object subscriber, Type
|
|
targetSourceType )</literal>: The subscriber receives all events
|
|
from a source object of a particular type for which it has
|
|
matching handler methods.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void Unsubscribe(object subscriber )</literal>:
|
|
Unsubscribe all events from the source object for which it has
|
|
matching handler methods.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>void Unsubscribe(object subscriber, Type
|
|
targetSourceType )</literal>: Unsubscribe all events from a source
|
|
object of a particular type for which it has matching handler
|
|
methods.</para>
|
|
</listitem>
|
|
</itemizedlist> <literal>IApplicationContext</literal> implements this
|
|
interface and delegates the implementation to an instance of
|
|
<literal>Spring.Objects.Events.Support.EventRegistry</literal>. You are
|
|
free to create and use as many EventRegistries as you like but since it
|
|
is common to use only one in an application,
|
|
<literal>IApplicationContext</literal> provides convenient access to a
|
|
single instance.</para>
|
|
|
|
<para>Within the
|
|
<literal>example/Spring/Spring.Examples.EventRegistry</literal>
|
|
directory you will find an example on how to use this functionality.
|
|
When you open up the project, the most interesting file is the
|
|
EventRegistryApp.cs file. This application loads a set of object
|
|
definitions from the application configuration file into an
|
|
<literal>IApplicationContext</literal> instance. From there, three
|
|
objects are loaded up: one publisher and two subscribers. The publisher
|
|
publishes its events to the <literal>IApplicationContext</literal>
|
|
instance: <programlisting language="csharp">// Create the Application context using configuration file
|
|
IApplicationContext ctx = ContextRegistry.GetContext();
|
|
|
|
// Gets the publisher from the application context
|
|
MyEventPublisher publisher = (MyEventPublisher)ctx.GetObject("MyEventPublisher");
|
|
|
|
// Publishes events to the context.
|
|
ctx.PublishEvents( publisher );
|
|
</programlisting> One of the two subscribers subscribes to all events
|
|
published to the <literal>IApplicationContext</literal> instance, using
|
|
the publisher type as the filter criteria.<programlisting
|
|
language="csharp">// Gets first instance of subscriber
|
|
MyEventSubscriber subscriber = (MyEventSubscriber)ctx.GetObject("MyEventSubscriber");
|
|
|
|
// Gets second instance of subscriber
|
|
MyEventSubscriber subscriber2 = (MyEventSubscriber)ctx.GetObject("MyEventSubscriber");
|
|
|
|
// Subscribes the first instance to the any events published by the type MyEventPublisher
|
|
ctx.Subscribe( subscriber, typeof(MyEventPublisher) );</programlisting> This
|
|
will wire the first subscriber to the original event publisher. Anytime
|
|
the event publisher fires an event,
|
|
(<literal>publisher.ClientMethodThatTriggersEvent1();</literal>) the
|
|
first subscriber will handle the event, but the second subscriber will
|
|
not. This allows for selective subscription, regardless of the original
|
|
prototype definition.</para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="context-functionality-events">
|
|
<title>Event notification from
|
|
<literal>IApplicationContext</literal></title>
|
|
|
|
<para>Event handling in the <literal>IApplicationContext</literal> is
|
|
provided through the <literal>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"><object id="emailer" type="Example.EmailObject">
|
|
<property name="blackList">
|
|
<list>
|
|
<value>black@list.org</value>
|
|
<value>white@list.org</value>
|
|
<value>john@doe.org</value>
|
|
</list>
|
|
</property>
|
|
</object>
|
|
|
|
<object id="blackListListener" type="Example.BlackListNotifier">
|
|
<property name="notificationAddress">
|
|
<value>spam@list.org</value>
|
|
</property>
|
|
</object></programlisting> and then, the actual objects: <programlisting
|
|
language="csharp">public class EmailObject : IApplicationContextAware {
|
|
|
|
// the blacklist
|
|
private IList blackList;
|
|
|
|
public IList BlackList
|
|
{
|
|
set { this.blackList = value; }
|
|
}
|
|
|
|
public IApplicationContext ApplicationContext
|
|
{
|
|
set { this.ctx = value; }
|
|
}
|
|
|
|
public void SendEmail(string address, string text) {
|
|
if (blackList.contains(address))
|
|
{
|
|
BlackListEvent evt = new BlackListEvent(address, text);
|
|
ctx.publishEvent(evt);
|
|
return;
|
|
}
|
|
// send email...
|
|
}
|
|
}
|
|
|
|
public class BlackListNotifier : 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"><spring>
|
|
<context>
|
|
<resource uri="assembly://MyAssembly/MyProject/root-objects.xml"/>
|
|
<context name="mySubContext">
|
|
<resource uri="file://objects.xml"/>
|
|
</context>
|
|
</context>
|
|
</spring></programlisting></para>
|
|
|
|
<para>Do not call ContextRegistry.GetContext within a constructor as it
|
|
will result in and endless recursion. (This is scheduled to be fixed in
|
|
1.1.1) In this case it is quite likely you can use the
|
|
IApplicationContextAware interface and then retrieve other objects in a
|
|
service locator style inside an initialization method.</para>
|
|
|
|
<para>The <literal>ContextRegistry.Clear()</literal> method will remove
|
|
all contexts. On .NET 2.0, this will also call the ConfigurationManager's
|
|
RefreshSection method so that the Spring context configuration section
|
|
will be reread from disk when it is retrieved again. Note that in a web
|
|
application RefeshSection will not work as advertised and you will need to
|
|
touch the web.config files to reload a configuration.</para>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Stereotype attributes</title>
|
|
|
|
<para>Beginning with Spring 1.2, the [Repository] attribute was introduced
|
|
as a marker for any class that fulfills the role or stereotype of a
|
|
repository (a.k.a. Data Access Object or DAO). Among the possibilities for
|
|
leveraging such a marker is the automatic translation of exceptions as
|
|
described in <link linkend="orm-hibernate-straight-ex">Exception
|
|
Translation.</link></para>
|
|
|
|
<para>Spring 1.2 introduces further stereotype annotations: [Component]
|
|
and [Service]. [Component] serves as a generic stereotype for any
|
|
Spring-managed component; whereas, [Repository] and [Service] serve as
|
|
specializations of [Component] for more specific use cases (e.g., in the
|
|
persistence and service layers, respectively). The ASP.NET MVC
|
|
[Controller] attribute will serve this purpose for the controller layer.
|
|
What this means is that you can annotate your component classes with
|
|
[Component], but by annotating them with [Repository] or [Service] your
|
|
classes are more properly suited for processing by tools or associating
|
|
with aspects. For example, these stereotype annotations make ideal targets
|
|
for pointcuts. Of course, it is also possible that [Repository] and
|
|
[Service] may carry additional semantics in future releases of the Spring
|
|
Framework. Thus, if you are making a decision between using [Component] or
|
|
[Service] for your service layer, [Service] is clearly the better choice.
|
|
Similarly, as stated above, [Repository] is already supported as a marker
|
|
for automatic exception translation in your persistence layer. The next
|
|
version of Spring will use the [Component] attribute to perform attribute
|
|
based autowiring by-type as in the Spring Java Framework.</para>
|
|
</sect1>
|
|
</chapter>
|