SPRNET-620 - Support for Collection Merging in Parent/Child Object Definitions
This commit is contained in:
@@ -199,7 +199,7 @@
|
||||
<!-- additional collaborators and configuration for this object go here -->
|
||||
</object>
|
||||
|
||||
<!-- more bean definitions for services go here -->
|
||||
<!-- more object definitions for services go here -->
|
||||
|
||||
</objects></programlisting>The following example shows the data access
|
||||
objects <literal>(daos.xml)</literal> configuration file:</para>
|
||||
@@ -207,14 +207,14 @@
|
||||
<programlisting><objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object id="AccountDao" type="Petstore.Dao.HibernateAccountDao, PetStore">
|
||||
<!-- additional collaborators and configuration for this bean go here -->
|
||||
<!-- additional collaborators and configuration for this object go here -->
|
||||
</object>
|
||||
|
||||
<object id="ItemDao" type="Petstore.Dao.HibernateItemDao, PetStore">
|
||||
<!-- additional collaborators and configuration for this bean go here -->
|
||||
<!-- additional collaborators and configuration for this object go here -->
|
||||
</object>
|
||||
|
||||
<!-- more bean definitions for data access objects go here -->
|
||||
<!-- more object definitions for data access objects go here -->
|
||||
</objects></programlisting>
|
||||
|
||||
<para>In the preceeding example, the service layer consists of the class
|
||||
@@ -436,7 +436,7 @@
|
||||
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
|
||||
bean definitions according to the Spring Schema.</para>
|
||||
object definitions according to the Spring Schema.</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
|
||||
@@ -453,7 +453,7 @@
|
||||
<para>The <literal>IApplicationContext</literal> enables you to read
|
||||
object definitions and access them as follows:</para>
|
||||
|
||||
<programlisting language="csharp">// create and configure beans
|
||||
<programlisting language="csharp">// create and configure objects
|
||||
IApplicationContext context = new XmlApplicationContext("services.xml", "daos.xml");
|
||||
|
||||
// retrieve configured instance
|
||||
@@ -1037,8 +1037,8 @@ public class TestGenericObjectFactory
|
||||
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 bean. This process is fundamentally the inverse to the case when the
|
||||
bean itself is controlling the instantiation or location of its
|
||||
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
|
||||
@@ -1725,9 +1725,9 @@ public class MixedIocObject
|
||||
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' bean is a
|
||||
prototype bean, this typo and the resulting exception may only be
|
||||
discovered long after the container is deployed.</para>
|
||||
'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
|
||||
@@ -1770,7 +1770,7 @@ public class MixedIocObject
|
||||
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>bean</literal>,
|
||||
the id/name of the object through the <literal>object</literal>,
|
||||
<literal>local</literal>, or <literal>parent</literal>
|
||||
attributes.</para>
|
||||
|
||||
@@ -1802,16 +1802,16 @@ public class MixedIocObject
|
||||
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 us ethis object reference variant mainly when you
|
||||
have a hierarchy of containers and you want to wrap an existing bean
|
||||
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 bean.<programlisting language="myxml"><!-- in the parent context -->
|
||||
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 -->
|
||||
<!-- insert dependencies as required as here -->
|
||||
</object></programlisting><programlisting><!-- in the child (descendant) context -->
|
||||
<object id="AccountService" <-- notice that the name of this bean is the same as the name of the 'parent' bean
|
||||
type="Spring.Aop.Framework.ProxyFactoryBean, Spring.Aop">
|
||||
<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 bean -->
|
||||
<ref parent="AccountService"/> <-- notice how we refer to the parent object -->
|
||||
</property>
|
||||
<!-- insert other configuration and dependencies as required as here -->
|
||||
</object></programlisting></para>
|
||||
@@ -1841,7 +1841,7 @@ public class MixedIocObject
|
||||
<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 beans other than into the
|
||||
to inject inner objects into collaborating objects other than into the
|
||||
enclosing object.</para>
|
||||
</sect3>
|
||||
|
||||
@@ -2032,6 +2032,85 @@ public class MixedIocObject
|
||||
</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> <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
|
||||
sales=sales@example.com
|
||||
support=support@example.co.uk</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>
|
||||
|
||||
@@ -2388,11 +2467,11 @@ source.OnClick(); // First eventListener1.HandleEvent is invoked, then eventList
|
||||
<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 beans
|
||||
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
|
||||
beans to be initialized before the bean using this element is
|
||||
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">
|
||||
@@ -2452,13 +2531,13 @@ source.OnClick(); // First eventListener1.HandleEvent is invoked, then eventList
|
||||
<literal>IApplicationContext</literal> is starting up, whereas the
|
||||
<literal>not.lazy</literal> object is eagerly pre-instantiated.</para>
|
||||
|
||||
<para>However, when a lazy-initialized bean is a dependency of a
|
||||
<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
|
||||
bean at startup, because it must satisfy the singleton's dependencies.
|
||||
The lazy-initialized bean is injected into a singleton object elsewhere
|
||||
that is not lazy-initialized.</para>
|
||||
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
|
||||
@@ -3460,7 +3539,7 @@ public class MyClassFactory
|
||||
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
|
||||
bean is instantiated and then dependency-injected into the singleton
|
||||
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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user