You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1648 lines
80 KiB
1648 lines
80 KiB
<?xml version="1.0" encoding="UTF-8"?> |
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" |
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> |
|
<section id="beans-dependencies"> |
|
<title>Dependencies</title> |
|
|
|
<para>A typical enterprise application does not consist of a single object (or |
|
bean in the Spring parlance). 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 |
|
bean definitions that stand alone to a fully realized application where |
|
objects collaborate to achieve a goal.</para> |
|
|
|
<section id="beans-factory-collaborators"> |
|
<title>Dependency injection</title> |
|
|
|
<!-- MLP: Beverly review the following two paragraphs --> |
|
|
|
<para><emphasis>Dependency injection</emphasis> (DI) is a process whereby |
|
objects define their dependencies, that is, the other objects they work |
|
with, only through constructor arguments, arguments to a factory method, |
|
or properties that are set on the object instance after it is constructed |
|
or returned from a factory method. The container then |
|
<emphasis>injects</emphasis> those dependencies when it creates the bean. |
|
This process is fundamentally the inverse, hence the name |
|
<emphasis>Inversion of Control</emphasis> (IoC), of the bean itself |
|
controlling the instantiation or location of its dependencies on its own |
|
by using direct construction of classes, or the <emphasis>Service |
|
Locator</emphasis> pattern.</para> |
|
|
|
<para>Code is cleaner with the DI principle 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. As such, your classes become easier to test, in particular |
|
when the dependencies are on interfaces or abstract base classes, which |
|
allow for stub or mock implementations to be used in unit tests.</para> |
|
|
|
<para>DI exists in two major variants, <link |
|
linkend="beans-constructor-injection">Constructor-based dependency |
|
injection</link> and <link linkend="beans-setter-injection">Setter-based |
|
dependency injection</link>.</para> |
|
|
|
<section id="beans-constructor-injection"> |
|
<title>Constructor-based dependency injection</title> |
|
|
|
<para><emphasis>Constructor-based</emphasis> DI is accomplished by the |
|
container invoking a constructor with a number of arguments, each |
|
representing a dependency. Calling a <literal>static</literal> factory |
|
method with specific arguments to construct the bean is nearly |
|
equivalent, and this discussion treats arguments to a constructor and to |
|
a <literal>static</literal> factory method similarly. The following |
|
example shows a class that can only be dependency-injected with |
|
constructor injection. Notice that there is nothing |
|
<emphasis>special</emphasis> about this class, it is a POJO that has no |
|
dependencies on container specific interfaces, base classes or |
|
annotations.</para> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
<lineannotation>// the <classname>SimpleMovieLister</classname> has a dependency on a <interfacename>MovieFinder</interfacename></lineannotation> |
|
private MovieFinder movieFinder; |
|
|
|
<lineannotation>// a constructor so that the Spring container can 'inject' a <interfacename>MovieFinder</interfacename></lineannotation> |
|
public SimpleMovieLister(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
|
|
<lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation> |
|
}</programlisting> |
|
|
|
<section id="beans-factory-ctor-arguments-resolution"> |
|
<title>Constructor argument resolution</title> |
|
|
|
<para>Constructor argument resolution matching occurs using the |
|
argument's type. If no potential ambiguity exists in the constructor |
|
arguments of a bean definition, then the order in which the |
|
constructor arguments are defined in a bean definition is the order in |
|
which those arguments are supplied to the appropriate constructor when |
|
the bean is being instantiated. Consider the following class:</para> |
|
|
|
<programlisting language="java">package x.y; |
|
|
|
public class Foo { |
|
|
|
public Foo(Bar bar, Baz baz) { |
|
<lineannotation>// ...</lineannotation> |
|
} |
|
}</programlisting> |
|
|
|
<para>No potential ambiguity exists, assuming that |
|
<classname>Bar</classname> and <classname>Baz</classname> classes are |
|
not related by inheritance. Thus the following configuration works |
|
fine, and you do not need to specify the constructor argument indexes |
|
and/or types explicitly in the |
|
<literal><constructor-arg/></literal> element.</para> |
|
|
|
<programlisting language="xml"><beans> |
|
<bean id="foo" class="x.y.Foo"> |
|
<constructor-arg ref="bar"/> |
|
<constructor-arg ref="baz"/> |
|
</bean> |
|
|
|
<bean id="bar" class="x.y.Bar"/> |
|
<bean id="baz" class="x.y.Baz"/> |
|
|
|
</beans></programlisting> |
|
|
|
<para>When another bean is referenced, the type is known, and matching |
|
can occur (as was the case with the preceding example). When a simple |
|
type is used, such as |
|
<literal><value>true<value></literal>, Spring cannot |
|
determine the type of the value, and so cannot match by type without |
|
help. Consider the following class:</para> |
|
|
|
<programlisting language="java">package examples; |
|
|
|
public class ExampleBean { |
|
|
|
<lineannotation>// No. of years to the calculate the Ultimate Answer</lineannotation> |
|
private int years; |
|
|
|
<lineannotation>// The Answer to Life, the Universe, and Everything</lineannotation> |
|
private String ultimateAnswer; |
|
|
|
public ExampleBean(int years, String ultimateAnswer) { |
|
this.years = years; |
|
this.ultimateAnswer = ultimateAnswer; |
|
} |
|
}</programlisting> |
|
|
|
<section id="beans-factory-ctor-arguments-type"> |
|
<title>Constructor argument type matching</title> |
|
|
|
<para>In the preceding scenario, the container |
|
<emphasis>can</emphasis> use type matching with simple types if you |
|
explicitly specify the type of the constructor argument using the |
|
<literal>type</literal> attribute. For example:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
<constructor-arg type="int" value="7500000"/> |
|
<constructor-arg type="java.lang.String" value="42"/> |
|
</bean></programlisting> |
|
</section> |
|
|
|
<section id="beans-factory-ctor-arguments-index"> |
|
<title>Constructor argument index</title> |
|
|
|
<para>Use the <literal>index</literal> attribute to specify explicitly |
|
the index of constructor arguments. For example:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
<constructor-arg index="0" value="7500000"/> |
|
<constructor-arg index="1" value="42"/> |
|
</bean></programlisting> |
|
|
|
<para>In addition to resolving the ambiguity of multiple simple |
|
values, specifying an index resolves ambiguity where a constructor |
|
has two arguments of the same type. Note that the <emphasis>index is |
|
0 based</emphasis>.</para> |
|
</section> |
|
|
|
<section id="beans-factory-ctor-arguments-name"> |
|
<title>Constructor argument name</title> |
|
|
|
<para>As of Spring 3.0 you can also use the constructor parameter |
|
name for value disambiguation:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
<constructor-arg name="years" value="7500000"/> |
|
<constructor-arg name="ultimateanswer" value="42"/> |
|
</bean></programlisting> |
|
|
|
<para>Keep in mind that to make this work out of the box your code |
|
must be compiled with the debug flag enabled so that Spring can |
|
look up the parameter name from the constructor. If you can't compile |
|
your code with debug flag (or don't want to) you can use |
|
<interfacename><ulink |
|
url="http://download.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.html">@ConstructorProperties</ulink></interfacename> |
|
JDK annotation to explicitly name your constructor arguments. The |
|
sample class would then have to look as follows:</para> |
|
|
|
<programlisting language="java">package examples; |
|
|
|
public class ExampleBean { |
|
|
|
<lineannotation>// </lineannotation>Fields omitted |
|
|
|
@ConstructorProperties({"years", "ultimateAnswer"}) |
|
public ExampleBean(int years, String ultimateAnswer) { |
|
this.years = years; |
|
this.ultimateAnswer = ultimateAnswer; |
|
} |
|
}</programlisting> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-setter-injection"> |
|
<title>Setter-based dependency injection</title> |
|
|
|
<para><emphasis>Setter-based</emphasis> DI is accomplished by the |
|
container calling setter methods on your beans after invoking a |
|
no-argument constructor or no-argument <literal>static</literal> factory |
|
method to instantiate your bean.</para> |
|
|
|
<para>The following example shows a class that can only be |
|
dependency-injected using pure setter injection. This class is |
|
conventional Java. It is a POJO that has no dependencies on container |
|
specific interfaces, base classes or annotations.</para> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
<lineannotation>// the <classname>SimpleMovieLister</classname> has a dependency on the <interfacename>MovieFinder</interfacename></lineannotation> |
|
private MovieFinder movieFinder; |
|
|
|
<lineannotation>// a setter method so that the Spring container can 'inject' a <interfacename>MovieFinder</interfacename></lineannotation> |
|
public void setMovieFinder(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
|
|
<lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> supports |
|
constructor- and setter-based DI for the beans it manages. It also |
|
supports setter-based DI after some dependencies are already injected |
|
through the constructor approach. You configure the dependencies in the |
|
form of a <interfacename>BeanDefinition</interfacename>, which you use |
|
with <interfacename>PropertyEditor</interfacename> instances to convert |
|
properties from one format to another. However, most Spring users do not |
|
work with these classes directly (programmatically), but rather with an |
|
XML definition file that is then converted internally into instances of |
|
these classes, and used to load an entire Spring IoC container |
|
instance.</para> |
|
|
|
<sidebar> |
|
<title>Constructor-based or setter-based DI?</title> |
|
|
|
<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. Note that the use |
|
of a <link linkend="beans-required-annotation">@Required</link> |
|
annotation on a setter can be used to make setters required |
|
dependencies.</para> |
|
|
|
<para>The Spring team generally advocates setter injection, because |
|
large numbers of constructor arguments can get unwieldy, especially |
|
when properties are optional. Setter methods also make objects of that |
|
class amenable to reconfiguration or re-injection later. Management |
|
through <link linkend="jmx">JMX MBeans</link> 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> |
|
</sidebar> |
|
</section> |
|
|
|
<section> |
|
<title>Dependency resolution process</title> |
|
|
|
<para>The container performs bean dependency resolution as follows:</para> |
|
|
|
<!-- MLP: Beverly to review all list items--> |
|
|
|
<orderedlist> |
|
<listitem> |
|
<para>The <interfacename>ApplicationContext</interfacename> is created |
|
and initialized with configuration metadata that describes all the |
|
beans. Configuration metadata can be specified via XML, Java code or |
|
annotations.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>For each bean, its dependencies are 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 are provided to the bean, |
|
<emphasis>when the bean is actually created</emphasis>.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Each property or constructor argument is an actual definition of |
|
the value to set, or a reference to another bean in the |
|
container.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Each property or constructor argument which is a value is |
|
converted from its specified format to the actual type of that |
|
property or constructor argument. By default Spring 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>boolean</literal>, etc.</para> |
|
</listitem> |
|
</orderedlist> |
|
|
|
<para>The Spring container validates the configuration of each bean as the |
|
container is created, including the validation of whether bean reference |
|
properties refer to valid beans. However, the bean properties themselves |
|
are not set until the bean <emphasis>is actually created</emphasis>. |
|
Beans that are singleton-scoped and set to be pre-instantiated (the |
|
default) are created when the container is created. Scopes are defined |
|
in <xref linkend="beans-factory-scopes"/> Otherwise, the bean is created |
|
only when it is requested. Creation of a bean potentially causes a graph |
|
of beans to be created, as the bean's dependencies and its dependencies' |
|
dependencies (and so on) are created and assigned.</para> |
|
|
|
<sidebar> |
|
<title>Circular dependencies</title> |
|
|
|
<para>If you use predominantly constructor injection, it is possible to |
|
create an unresolvable circular dependency scenario.</para> |
|
|
|
<para>For example: Class A requires an instance of class B through |
|
constructor injection, and class B requires an instance of class A |
|
through constructor injection. If you configure beans for classes A |
|
and B to be injected into each other, the Spring IoC container detects |
|
this circular reference at runtime, and throws a |
|
<classname>BeanCurrentlyInCreationException</classname>.</para> |
|
|
|
<para>One possible solution is to edit the source code of some classes |
|
to be configured by setters rather than constructors. Alternatively, |
|
avoid constructor injection and use setter injection only. In other |
|
words, although it is not recommended, you can configure circular |
|
dependencies with setter injection.</para> |
|
|
|
<para>Unlike the <emphasis>typical</emphasis> case (with no circular |
|
dependencies), a circular dependency between bean A and bean B forces |
|
one of the beans 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 to do the right thing. It detects |
|
configuration problems, such as references to non-existent beans and |
|
circular dependencies, at container load-time. Spring sets properties |
|
and resolves dependencies as late as possible, when the bean 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 bean throws an exception as a result of a missing or invalid |
|
property. This potentially delayed visibility of some configuration |
|
issues is why <interfacename>ApplicationContext</interfacename> |
|
implementations by default pre-instantiate singleton beans. At the cost |
|
of some upfront time and memory to create these beans before they are |
|
actually needed, you discover configuration issues when the |
|
<interfacename>ApplicationContext</interfacename> is created, not later. |
|
You can still override this default behavior so that singleton beans |
|
will lazy-initialize, rather than be pre-instantiated.</para> |
|
|
|
<para>If no circular dependencies exist, when one or more collaborating |
|
beans are being injected into a dependent bean, each collaborating bean |
|
is <emphasis>totally</emphasis> configured prior to being injected into |
|
the dependent bean. This means that if bean A has a dependency on bean |
|
B, the Spring IoC container completely configures bean B prior to |
|
invoking the setter method on bean A. In other words, the bean is |
|
instantiated (if not a pre-instantiated singleton), its dependencies are |
|
set, and the relevant lifecycle methods (such as a <link |
|
linkend="beans-factory-lifecycle-initializingbean">configured init |
|
method</link> or the <link |
|
linkend="beans-factory-lifecycle-initializingbean">IntializingBean |
|
callback method</link>) are invoked.</para> |
|
</section> |
|
|
|
<section id="beans-some-examples"> |
|
<title>Examples of dependency injection</title> |
|
|
|
<para>The following example uses XML-based configuration metadata for |
|
setter-based DI. A small part of a Spring XML configuration file |
|
specifies some bean definitions:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
|
|
<lineannotation><!-- setter injection using the nested <literal><ref/></literal> element --></lineannotation> |
|
<property name="beanOne"><ref bean="anotherExampleBean"/></property> |
|
|
|
<lineannotation><!-- setter injection using the neater 'ref' attribute --></lineannotation> |
|
<property name="beanTwo" ref="yetAnotherBean"/> |
|
<property name="integerProperty" value="1"/> |
|
</bean> |
|
|
|
<bean id="anotherExampleBean" class="examples.AnotherBean"/> |
|
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/></programlisting> |
|
|
|
<programlisting language="java">public class ExampleBean { |
|
|
|
private AnotherBean beanOne; |
|
private YetAnotherBean beanTwo; |
|
private int i; |
|
|
|
public void setBeanOne(AnotherBean beanOne) { |
|
this.beanOne = beanOne; |
|
} |
|
|
|
public void setBeanTwo(YetAnotherBean beanTwo) { |
|
this.beanTwo = beanTwo; |
|
} |
|
|
|
public void setIntegerProperty(int i) { |
|
this.i = i; |
|
} |
|
}</programlisting> |
|
|
|
<para>In the preceding example, setters are declared to match against the |
|
properties specified in the XML file. The following example uses |
|
constructor-based DI:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
|
|
<lineannotation><!-- constructor injection using the nested <literal><ref/></literal> element --></lineannotation> |
|
<constructor-arg> |
|
<ref bean="anotherExampleBean"/> |
|
</constructor-arg> |
|
|
|
<lineannotation><!-- constructor injection using the neater 'ref' attribute --></lineannotation> |
|
<constructor-arg ref="yetAnotherBean"/> |
|
|
|
<constructor-arg type="int" value="1"/> |
|
</bean> |
|
|
|
<bean id="anotherExampleBean" class="examples.AnotherBean"/> |
|
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/></programlisting> |
|
|
|
<programlisting language="java">public class ExampleBean { |
|
|
|
private AnotherBean beanOne; |
|
private YetAnotherBean beanTwo; |
|
private int i; |
|
|
|
public ExampleBean( |
|
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { |
|
this.beanOne = anotherBean; |
|
this.beanTwo = yetAnotherBean; |
|
this.i = i; |
|
} |
|
}</programlisting> |
|
|
|
<para>The constructor arguments specified in the bean definition will be |
|
used as arguments to the constructor of the |
|
<classname>ExampleBean</classname>.</para> |
|
|
|
<para>Now consider a variant of this example, where instead of using a |
|
constructor, Spring is told to call a <literal>static</literal> factory |
|
method to return an instance of the object:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean" |
|
factory-method="createInstance"> |
|
<constructor-arg ref="anotherExampleBean"/> |
|
<constructor-arg ref="yetAnotherBean"/> |
|
<constructor-arg value="1"/> |
|
</bean> |
|
|
|
<bean id="anotherExampleBean" class="examples.AnotherBean"/> |
|
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/></programlisting> |
|
|
|
<programlisting language="java">public class ExampleBean { |
|
|
|
<lineannotation>// a private constructor</lineannotation> |
|
private ExampleBean(...) { |
|
... |
|
} |
|
<lineannotation> |
|
// a static factory method; the arguments to this method can be |
|
// considered the dependencies of the bean that is returned, |
|
// regardless of how those arguments are actually used.</lineannotation> |
|
public static ExampleBean createInstance ( |
|
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { |
|
|
|
ExampleBean eb = new ExampleBean (...); |
|
<lineannotation>// some other operations...</lineannotation> |
|
return eb; |
|
} |
|
}</programlisting> |
|
|
|
<para>Arguments to the <literal>static</literal> 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 that contains the <literal>static</literal> |
|
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-bean</literal> attribute instead of |
|
the <literal>class</literal> attribute), so details will not be |
|
discussed here.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-properties-detailed"> |
|
<title>Dependencies and configuration in detail</title> |
|
|
|
<para>As mentioned in the previous section, you can define bean properties |
|
and constructor arguments as references to other managed beans |
|
(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> |
|
|
|
<section id="beans-value-element"> |
|
<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. <link |
|
linkend="beans-beans-conversion">As mentioned previously</link>, |
|
JavaBeans <literal>PropertyEditors</literal> are used to convert these |
|
string values from a <classname>String</classname> to the actual type of |
|
the property or argument.</para> |
|
|
|
<programlisting language="xml"><bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> |
|
|
|
<lineannotation><!-- results in a <methodname>setDriverClassName(String)</methodname> call --></lineannotation> |
|
<property name="driverClassName" value="com.mysql.jdbc.Driver"/> |
|
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/> |
|
<property name="username" value="root"/> |
|
<property name="password" value="masterkaoli"/> |
|
</bean></programlisting> |
|
|
|
<para>The following example uses the <link linkend="beans-p-namespace" |
|
>p-namespace</link> for even more succinct XML configuration.</para> |
|
|
|
<programlisting language="xml"><beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:p="http://www.springframework.org/schema/p" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" |
|
destroy-method="close" |
|
p:driverClassName="com.mysql.jdbc.Driver" |
|
p:url="jdbc:mysql://localhost:3306/mydb" |
|
p:username="root" |
|
p:password="masterkaoli"/> |
|
|
|
</beans> |
|
|
|
</programlisting> |
|
|
|
<para>The preceding XML is more succinct; however, typos are discovered at |
|
runtime rather than design time, unless you use an IDE such as <ulink |
|
url="http://www.jetbrains.com/idea/">IntelliJ IDEA</ulink> or the <ulink |
|
url="http://www.springsource.com/products/sts">SpringSource Tool |
|
Suite</ulink> (STS) that support automatic property completion when you |
|
create bean definitions. Such IDE assistance is highly |
|
recommended.</para> |
|
|
|
<para>You can also configure a <classname>java.util.Properties</classname> |
|
instance as:</para> |
|
|
|
<programlisting language="xml"><bean id="mappings" |
|
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> |
|
|
|
<lineannotation><!-- typed as a <classname>java.util.Properties</classname> --></lineannotation> |
|
<property name="properties"> |
|
<value> |
|
jdbc.driver.className=com.mysql.jdbc.Driver |
|
jdbc.url=jdbc:mysql://localhost:3306/mydb |
|
</value> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para>The Spring container converts the text inside the |
|
<literal><value/></literal> element into a |
|
<classname>java.util.Properties</classname> instance by using the |
|
JavaBeans <interfacename>PropertyEditor</interfacename> mechanism. This |
|
is a nice shortcut, and is one of a few places where the Spring team do |
|
favor the use of the nested <literal><value/></literal> element |
|
over the <literal>value</literal> attribute style.</para> |
|
|
|
<section id="beans-idref-element"> |
|
<title>The <literal>idref</literal> element</title> |
|
|
|
<para>The <literal>idref</literal> element is simply an error-proof way |
|
to pass the <emphasis>id</emphasis> (string value - not a reference) |
|
of another bean in the container to a |
|
<literal><constructor-arg/></literal> or |
|
<literal><property/></literal> element.</para> |
|
|
|
<programlisting language="xml"><bean id="theTargetBean" class="..."/> |
|
|
|
<bean id="theClientBean" class="..."> |
|
<property name="targetName"> |
|
<idref bean="theTargetBean" /> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para>The above bean definition snippet is <emphasis>exactly</emphasis> |
|
equivalent (at runtime) to the following snippet:</para> |
|
|
|
<programlisting language="xml"><bean id="theTargetBean" class="..." /> |
|
|
|
<bean id="client" class="..."> |
|
<property name="targetName" value="theTargetBean" /> |
|
</bean></programlisting> |
|
|
|
<para>The first form is preferable to the second, because using the |
|
<literal>idref</literal> tag allows the container to validate |
|
<emphasis>at deployment time</emphasis> that the referenced, named |
|
bean actually exists. In the second variation, no validation is |
|
performed on the value that is passed to the |
|
<literal>targetName</literal> property of the |
|
<literal>client</literal> bean. Typos are only discovered (with most |
|
likely fatal results) when the <literal>client</literal> bean is |
|
actually instantiated. If the <literal>client</literal> bean is a |
|
<link linkend="beans-factory-scopes">prototype</link> bean, this typo |
|
and the resulting exception may only be discovered long after the |
|
container is deployed.</para> |
|
|
|
<para>Additionally, if the referenced bean is in the same XML unit, and |
|
the bean name is the bean <emphasis>id</emphasis>, you can use the |
|
<literal>local</literal> attribute, which allows the XML parser itself |
|
to validate the bean id earlier, at XML document parse time.</para> |
|
|
|
<programlisting language="xml"><property name="targetName"> |
|
<lineannotation><!-- a bean with id '<literal>theTargetBean</literal>' must exist; otherwise an exception will be thrown --></lineannotation> |
|
<idref local="theTargetBean"/> |
|
</property></programlisting> |
|
|
|
<para>A common place (at least in versions earlier than Spring 2.0) |
|
where the <idref/> element brings value is in the configuration |
|
of <link linkend="aop-pfb-1">AOP interceptors</link> in a |
|
<classname>ProxyFactoryBean</classname> bean definition. Using |
|
<idref/> elements when you specify the interceptor names |
|
prevents you from misspelling an interceptor id.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-ref-element"> |
|
<title>References to other beans (collaborators)</title> |
|
|
|
<para>The <literal>ref</literal> element is the final element inside a |
|
<literal><constructor-arg/></literal> or |
|
<literal><property/></literal> definition element. Here you set |
|
the value of the specified property of a bean to be a reference to |
|
another bean (a collaborator) managed by the container. The referenced |
|
bean is a dependency of the bean whose property will be set, and it is |
|
initialized on demand as needed before the property is set. (If the |
|
collaborator is a singleton bean, it may be initialized already by the |
|
container.) All references are ultimately a reference to another object. |
|
Scoping and validation depend on whether you specify the id/name of the |
|
other object through the |
|
<literal>bean,<literal>local,</literal></literal> or |
|
<literal>parent</literal> attributes.</para> |
|
|
|
<para>Specifying the target bean through the <literal>bean</literal> |
|
attribute of the <literal><ref/></literal> tag is the most general |
|
form, and allows creation of a reference to any bean in the same |
|
container or parent container, regardless of whether it is in the same |
|
XML file. The value of the <literal>bean</literal> attribute may be the |
|
same as the <literal>id</literal> attribute of the target bean, or as |
|
one of the values in the <literal>name</literal> attribute of the target |
|
bean.</para> |
|
|
|
<programlisting language="xml"><ref bean="someBean"/></programlisting> |
|
|
|
<para>Specifying the target bean through 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 bean. The XML parser |
|
issues 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 as early as possible) if the target bean is in the same XML |
|
file.</para> |
|
|
|
<programlisting language="xml"><ref local="someBean"/></programlisting> |
|
|
|
<para>Specifying the target bean through the <literal>parent</literal> |
|
attribute creates a reference to a bean 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 bean, or one of the values in the <literal>name</literal> |
|
attribute of the target bean, and the target bean must be in a parent |
|
container of the current one. You use this bean reference variant mainly |
|
when you have a hierarchy of containers and you want to wrap an existing |
|
bean in a parent container with a proxy that will have the same name as |
|
the parent bean.</para> |
|
|
|
<programlisting language="xml"><lineannotation><!-- in the parent context --></lineannotation> |
|
<bean id="accountService" class="com.foo.SimpleAccountService"> |
|
<lineannotation><!-- insert dependencies as required as here --></lineannotation> |
|
</bean></programlisting> |
|
|
|
<programlisting language="xml"><lineannotation><!-- in the child (descendant) context --></lineannotation> |
|
<bean id="accountService" <lineannotation><-- bean name is the same as the parent bean --></lineannotation> |
|
class="org.springframework.aop.framework.ProxyFactoryBean"> |
|
<property name="target"> |
|
<ref parent="accountService"/> <lineannotation><!-- notice how we refer to the parent bean --></lineannotation> |
|
</property> |
|
<lineannotation><!-- insert other configuration and dependencies as required here --></lineannotation> |
|
</bean></programlisting> |
|
</section> |
|
|
|
<section id="beans-inner-beans"> |
|
<title>Inner beans</title> |
|
|
|
<para>A <literal><bean/></literal> element inside the |
|
<literal><property/></literal> or |
|
<literal><constructor-arg/></literal> elements defines a so-called |
|
<firstterm>inner bean</firstterm>.</para> |
|
|
|
<programlisting language="xml"><bean id="outer" class="..."> |
|
<lineannotation><!-- instead of using a reference to a target bean, simply define the target bean inline --></lineannotation> |
|
<property name="target"> |
|
<bean class="com.example.Person"> <lineannotation><!-- this is the inner bean --></lineannotation> |
|
<property name="name" value="Fiona Apple"/> |
|
<property name="age" value="25"/> |
|
</bean> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para>An inner bean definition does not require a defined id or name; the |
|
container ignores these values. It also ignores the |
|
<literal>scope</literal> flag. Inner beans are |
|
<emphasis>always</emphasis> anonymous and they are |
|
<emphasis>always</emphasis> scoped as <link |
|
linkend="beans-factory-scopes-prototype">prototypes</link>. It is |
|
<emphasis>not</emphasis> possible to inject inner beans into |
|
collaborating beans other than into the enclosing bean.</para> |
|
</section> |
|
|
|
<section id="beans-collection-elements"> |
|
<title>Collections</title> |
|
|
|
<para>In the <literal><list/></literal>, |
|
<literal><set/></literal>, <literal><map/></literal>, and |
|
<literal><props/></literal> elements, you set the properties and |
|
arguments of the Java <interfacename>Collection</interfacename> types |
|
<interfacename>List</interfacename>, <interfacename>Set</interfacename>, |
|
<interfacename>Map</interfacename>, and |
|
<interfacename>Properties</interfacename>, respectively.</para> |
|
|
|
<programlisting language="xml"><bean id="moreComplexObject" class="example.ComplexObject"> |
|
<lineannotation><!-- results in a setAdminEmails(<classname>java.util.Properties</classname>) call --></lineannotation> |
|
<property name="adminEmails"> |
|
<props> |
|
<prop key="administrator">administrator@example.org</prop> |
|
<prop key="support">support@example.org</prop> |
|
<prop key="development">development@example.org</prop> |
|
</props> |
|
</property> |
|
<lineannotation><!-- results in a setSomeList(<interfacename>java.util.List</interfacename>) call --></lineannotation> |
|
<property name="someList"> |
|
<list> |
|
<value>a list element followed by a reference</value> |
|
<ref bean="myDataSource" /> |
|
</list> |
|
</property> |
|
<lineannotation><!-- results in a setSomeMap(<interfacename>java.util.Map</interfacename>) call --></lineannotation> |
|
<property name="someMap"> |
|
<map> |
|
<entry key="an entry" value="just some string"/> |
|
<entry key ="a ref" value-ref="myDataSource"/> |
|
</map> |
|
</property> |
|
<lineannotation><!-- results in a setSomeSet(java.util.Set) call --></lineannotation> |
|
<property name="someSet"> |
|
<set> |
|
<value>just some string</value> |
|
<ref bean="myDataSource" /> |
|
</set> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para><emphasis>The value of a map key or value, or a set value, can also |
|
again be any of the following elements:</emphasis></para> |
|
|
|
<programlisting language="xml">bean | ref | idref | list | set | map | props | value | null</programlisting> |
|
|
|
<section id="beans-collection-elements-merging"> |
|
<title>Collection merging</title> |
|
|
|
<para>As of Spring 2.0, the container supports the |
|
<emphasis>merging</emphasis> of collections. An application developer |
|
can define a parent-style <literal><list/></literal>, |
|
<literal><map/></literal>, <literal><set/></literal> or |
|
<literal><props/></literal> element, and have child-style |
|
<literal><list/></literal>, <literal><map/></literal>, |
|
<literal><set/></literal> or <literal><props/></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 bean |
|
mechanism. Readers unfamiliar with parent and child bean definitions |
|
may wish to read the <link linkend="beans-child-bean-definitions" |
|
>relevant section</link> before continuing.</emphasis></para> |
|
|
|
<para>The following example demonstrates collection merging:</para> |
|
|
|
<programlisting language="xml"><beans> |
|
<bean id="parent" abstract="true" class="example.ComplexObject"> |
|
<property name="adminEmails"> |
|
<props> |
|
<prop key="administrator">administrator@example.com</prop> |
|
<prop key="support">support@example.com</prop> |
|
</props> |
|
</property> |
|
</bean> |
|
<bean id="child" parent="parent"> |
|
<property name="adminEmails"> |
|
<lineannotation><!-- the merge is specified on the *child* collection definition --></lineannotation> |
|
<props merge="true"> |
|
<prop key="sales">sales@example.com</prop> |
|
<prop key="support">support@example.co.uk</prop> |
|
</props> |
|
</property> |
|
</bean> |
|
<beans></programlisting> |
|
|
|
<para>Notice the use of the <literal>merge=true</literal> attribute on |
|
the <literal><props/></literal> element of the |
|
<literal>adminEmails</literal> property of the |
|
<literal>child</literal> bean definition. When the |
|
<literal>child</literal> bean is resolved and instantiated by the |
|
container, the resulting instance has an |
|
<literal>adminEmails</literal> <classname>Properties</classname> |
|
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 <classname>Properties</classname> collection's value set |
|
inherits all property elements from the parent |
|
<literal><props/></literal>, and the child's value for the |
|
<literal>support</literal> value overrides the value in the parent |
|
collection.</para> |
|
|
|
<para>This merging behavior applies similarly to the |
|
<literal><list/></literal>, <literal><map/></literal>, and |
|
<literal><set/></literal> collection types. In the specific case |
|
of the <literal><list/></literal> element, the semantics |
|
associated with the <classname>List</classname> collection type, that |
|
is, the notion of an <literal>ordered</literal> collection of values, |
|
is maintained; the parent's values precede all of the child list's |
|
values. In the case of the <interfacename>Map</interfacename>, |
|
<interfacename>Set</interfacename>, and |
|
<interfacename>Properties</interfacename> collection types, no |
|
ordering exists. Hence no ordering semantics are in effect for the |
|
collection types that underlie the associated |
|
<interfacename>Map</interfacename>, |
|
<interfacename>Set</interfacename>, and |
|
<interfacename>Properties</interfacename> implementation types that |
|
the container uses internally.</para> |
|
</section> |
|
|
|
<section> |
|
<title>Limitations of collection merging</title> |
|
|
|
<para>You cannot merge different collection types (such as a |
|
<interfacename>Map</interfacename> and a |
|
<interfacename>List</interfacename>), and if you do attempt to do so |
|
an appropriate <classname>Exception</classname> is thrown. The |
|
<literal>merge</literal> attribute must be specified on the lower, |
|
inherited, child definition; specifying the <literal>merge</literal> |
|
attribute on a parent collection definition is redundant and will not |
|
result in the desired merging. The merging feature is available only |
|
in Spring 2.0 and later.</para> |
|
</section> |
|
|
|
<section id="beans-collection-elements-strongly-typed"> |
|
<title>Strongly-typed collection (Java 5+ only)</title> |
|
|
|
<para>In Java 5 and later, you can use strongly typed collections (using |
|
generic types). That is, it is possible to declare a |
|
<interfacename>Collection</interfacename> type such that it can only |
|
contain <classname>String</classname> elements (for example). If you |
|
are using Spring to dependency-inject a strongly-typed |
|
<interfacename>Collection</interfacename> into a bean, you can take |
|
advantage of Spring's type-conversion support such that the elements |
|
of your strongly-typed <interfacename>Collection</interfacename> |
|
instances are converted to the appropriate type prior to being added |
|
to the <interfacename>Collection</interfacename>.</para> |
|
|
|
<programlisting language="java">public class Foo { |
|
|
|
private Map<String, Float> accounts; |
|
|
|
public void setAccounts(Map<String, Float> accounts) { |
|
this.accounts = accounts; |
|
} |
|
}</programlisting> |
|
|
|
<programlisting language="xml"><beans> |
|
<bean id="foo" class="x.y.Foo"> |
|
<property name="accounts"> |
|
<map> |
|
<entry key="one" value="9.99"/> |
|
<entry key="two" value="2.75"/> |
|
<entry key="six" value="3.99"/> |
|
</map> |
|
</property> |
|
</bean> |
|
</beans></programlisting> |
|
|
|
<para>When the <literal>accounts</literal> property of the |
|
<literal>foo</literal> bean is prepared for injection, the generics |
|
information about the element type of the strongly-typed |
|
<classname>Map<String, Float></classname> is available by |
|
reflection. Thus Spring's type conversion infrastructure recognizes |
|
the various value elements as being of type |
|
<classname>Float</classname>, and the string values <literal>9.99, |
|
2.75</literal>, and <literal>3.99</literal> are converted into an |
|
actual <classname>Float</classname> type.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-null-element"> |
|
<title>Null and empty string values</title> |
|
|
|
<para><!--Clarify difference between null value and empty string value?-->Spring |
|
treats empty arguments for properties and the like as empty |
|
<literal>Strings</literal>. The following XML-based configuration |
|
metadata snippet sets the email property to the empty |
|
<classname>String</classname> value ("")</para> |
|
|
|
<programlisting language="xml"><bean class="ExampleBean"> |
|
<property name="email" value=""/> |
|
</bean></programlisting> |
|
|
|
<para>The preceding example is equivalent to the following Java code: |
|
<methodname>exampleBean.setEmail("")</methodname>. The |
|
<literal><null/></literal> element handles <literal>null</literal> |
|
values. For example:</para> |
|
|
|
<programlisting language="xml"><bean class="ExampleBean"> |
|
<property name="email"><null/></property> |
|
</bean></programlisting> |
|
|
|
<para>The above configuration is equivalent to the following Java code: |
|
<methodname>exampleBean.setEmail(null)</methodname>.</para> |
|
</section> |
|
|
|
<section id="beans-p-namespace"> |
|
<title>XML shortcut with the p-namespace</title> |
|
|
|
<para>The p-namespace enables you to use the <literal>bean</literal> |
|
element's attributes, instead of nested |
|
<literal><property/></literal> elements, to describe your property |
|
values and/or collaborating beans.</para> |
|
|
|
<para>Spring 2.0 and later supports extensible configuration formats <link |
|
linkend="xsd-config">with namespaces</link>, which are based on an XML |
|
Schema definition. The <literal>beans</literal> configuration format |
|
discussed in this chapter is defined in an XML Schema document. However, |
|
the p-namespace is not defined in an XSD file and exists only in the |
|
core of Spring.</para> |
|
|
|
<para>The following example shows two XML snippets that resolve to the |
|
same result: The first uses standard XML format and the second uses the |
|
p-namespace.</para> |
|
|
|
<programlisting language="xml"><beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:p="http://www.springframework.org/schema/p" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<bean name="classic" class="com.example.ExampleBean"> |
|
<property name="email" value="foo@bar.com"/> |
|
</bean> |
|
|
|
<bean name="p-namespace" class="com.example.ExampleBean" |
|
p:email="foo@bar.com"/> |
|
</beans></programlisting> |
|
|
|
<para>The example shows an attribute in the p-namespace called email in |
|
the bean definition. This tells Spring to include a property |
|
declaration. As previously mentioned, the p-namespace does not have a |
|
schema definition, so you can set the name of the attribute to the |
|
property name.</para> |
|
|
|
<para>This next example includes two more bean definitions that both have |
|
a reference to another bean:</para> |
|
|
|
<programlisting language="xml"><beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:p="http://www.springframework.org/schema/p" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<bean name="john-classic" class="com.example.Person"> |
|
<property name="name" value="John Doe"/> |
|
<property name="spouse" ref="jane"/> |
|
</bean> |
|
|
|
<bean name="john-modern" |
|
class="com.example.Person" |
|
p:name="John Doe" |
|
p:spouse-ref="jane"/> |
|
|
|
<bean name="jane" class="com.example.Person"> |
|
<property name="name" value="Jane Doe"/> |
|
</bean> |
|
</beans></programlisting> |
|
|
|
<para>As you can see, this example includes not only a property value |
|
using the p-namespace, but also uses a special format to declare |
|
property references. Whereas the first bean definition uses |
|
<literal><property name="spouse" ref="jane"/></literal> to create |
|
a reference from bean <literal>john</literal> to bean |
|
<literal>jane</literal>, the second bean definition uses |
|
<literal>p:spouse-ref="jane"</literal> as an attribute to do the exact |
|
same thing. In this case <literal>spouse</literal> is the property name, |
|
whereas the <literal>-ref</literal> part indicates that this is not a |
|
straight value but rather a reference to another bean.</para> |
|
|
|
<note> |
|
<para>The p-namespace is not as flexible as the standard XML format. For |
|
example, the format for declaring property references clashes with |
|
properties that end in <literal>Ref</literal>, whereas the standard |
|
XML format does not. We recommend that you choose your approach |
|
carefully and communicate this to your team members, to avoid |
|
producing XML documents that use all three approaches at the same |
|
time.<!--Clarify ref to all three approaches.I see two, XML and namespace.--></para> |
|
</note> |
|
</section> |
|
|
|
<section id="beans-c-namespace"> |
|
<title>XML shortcut with the c-namespace</title> |
|
|
|
<para>Similar to the <xref linkend="beans-p-namespace"/>, the <emphasis>c-namespace</emphasis>, newly introduced in Spring 3.1, |
|
allows usage of inlined attributes for configuring the constructor arguments rather then nested <literal>constructor-arg</literal> |
|
elements.</para> |
|
|
|
<para>Let's review the examples from <xref linkend="beans-constructor-injection"/> with the <literal>c</literal> namespace:</para> |
|
|
|
<programlisting language="java"><beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:p="http://www.springframework.org/schema/c" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans.xsd"> |
|
|
|
<bean id="bar" class="x.y.Bar"/> |
|
<bean id="baz" class="x.y.Baz"/> |
|
|
|
<-- 'traditional' declaration --> |
|
<bean id="foo" class="x.y.Foo"> |
|
<constructor-arg ref="bar"/> |
|
<constructor-arg ref="baz"/> |
|
<constructor-arg value="foo@bar.com"/> |
|
</bean> |
|
|
|
<-- 'c-namespace' declaration --> |
|
<bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="foo@bar.com"> |
|
|
|
</beans></programlisting> |
|
|
|
<para>The <literal>c:</literal> namespace uses the same conventions as the <literal>p:</literal> one (trailing <literal>-ref</literal> for bean references) |
|
for setting the constructor arguments by their names. And just as well, it needs to be declared even though it is not defined in an XSD schema |
|
(but it exists inside the Spring core).</para> |
|
|
|
<para>For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), one can |
|
use fallback to the argument indexes:</para> |
|
|
|
<programlisting language="java"><-- 'c-namespace' index declaration --> |
|
<bean id="foo" class="x.y.Foo" c:_0-ref="bar" c:_1-ref="baz"></programlisting> |
|
|
|
<note>Due to the XML grammar, the index notation requires the presence of the leading <emphasis>_</emphasis> as XML attribute names cannot start |
|
with a number (even though some IDE allow it).</note> |
|
|
|
<para>In practice, the constructor resolution <link linkend="beans-factory-ctor-arguments-resolution">mechanism</link> is quite efficient in matching arguments so |
|
unless one really needs to, we recommend using the name notation through-out your configuration.</para> |
|
</section> |
|
|
|
<section id="beans-compound-property-names"> |
|
<title>Compound property names</title> |
|
|
|
<para>You can use compound or nested property names when you set bean |
|
properties, as long as all components of the path except the final |
|
property name are not <literal>null</literal>. Consider the following |
|
bean definition.</para> |
|
|
|
<programlisting language="xml"><bean id="foo" class="foo.Bar"> |
|
<property name="fred.bob.sammy" value="123" /> |
|
</bean></programlisting> |
|
|
|
<para>The <literal>foo</literal> bean has a <literal>fred</literal> |
|
property, which has a <literal>bob</literal> property, which has a |
|
<literal>sammy</literal> property, and that final |
|
<literal>sammy</literal> property is being set to the value |
|
<literal>123</literal>. In order for this to work, the |
|
<literal>fred</literal> property of <literal>foo</literal>, and the |
|
<literal>bob</literal> property of <literal>fred</literal> must not be |
|
<literal>null</literal> after the bean is constructed, or a |
|
<exceptionname>NullPointerException</exceptionname> is thrown.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-dependson"> |
|
<title>Using <literal>depends-on</literal></title> |
|
|
|
<para>If a bean is a dependency of another that usually means that one bean |
|
is set as a property of another. Typically you accomplish this with the |
|
<link linkend="beans-ref-element"><literal><ref/></literal> |
|
element</link> in XML-based configuration metadata. However, sometimes |
|
dependencies between beans are less direct; for example, a static |
|
initializer in a class needs to be triggered, such as database 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 initialized. The following example uses the |
|
<literal>depends-on</literal> attribute to express a dependency on a |
|
single bean:</para> |
|
|
|
<programlisting language="xml"><bean id="beanOne" class="ExampleBean" depends-on="<emphasis role="bold">manager</emphasis>"/> |
|
|
|
<bean id="<emphasis role="bold">manager</emphasis>" class="ManagerBean" /></programlisting> |
|
|
|
<para>To express a dependency on multiple beans, supply a list of bean names |
|
as the value of the <literal>depends-on</literal> attribute, with commas, |
|
whitespace and semicolons, used as valid delimiters:</para> |
|
|
|
<programlisting language="xml"><bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao"> |
|
<property name="manager" ref="manager" /> |
|
</bean> |
|
|
|
<bean id="manager" class="ManagerBean" /> |
|
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" /></programlisting> |
|
|
|
<note> |
|
<para>The <literal>depends-on</literal> attribute in the bean definition |
|
can specify both an initialization time dependency and, in the case of |
|
<link linkend="beans-factory-scopes-singleton">singleton</link> beans |
|
only, a corresponding destroy time dependency. Dependent beans that |
|
define a <literal>depends-on</literal> relationship with a given bean |
|
are destroyed first, prior to the given bean itself being destroyed. |
|
Thus <literal>depends-on</literal> can also control shutdown |
|
order.</para> |
|
</note> |
|
</section> |
|
|
|
<section id="beans-factory-lazy-init"> |
|
<title>Lazy-initialized |
|
beans<!--Changed to lazy-initialized from lazily instantiated because attribute is lazy-init, and there was a lot of inconsistency. --></title> |
|
|
|
<para>By default,<interfacename> ApplicationContext</interfacename> |
|
implementations eagerly create and configure all <link |
|
linkend="beans-factory-scopes-singleton">singleton</link> beans as part of |
|
the initialization process. Generally, this pre-instantiation is |
|
desirable, because errors in the configuration or surrounding environment |
|
are discovered immediately, as opposed to hours or even days later. When |
|
this behavior is <emphasis>not</emphasis> desirable, you can prevent |
|
pre-instantiation of a singleton bean by marking the bean definition as |
|
lazy-initialized. A lazy-initialized bean tells the IoC container to |
|
create a bean instance when it is first requested, rather than at |
|
startup.<!--Above, clarify what you mean by eagerly. Note, I've trimmed this section for conciseness, but info is still here.--></para> |
|
|
|
<para>In XML, this behavior is controlled by the |
|
<literal>lazy-init</literal> attribute on the |
|
<literal><bean/></literal> element; for example:</para> |
|
|
|
<programlisting language="xml"><bean id="lazy" class="com.foo.ExpensiveToCreateBean" <emphasis role="bold">lazy-init="true"</emphasis>/> |
|
|
|
<bean name="not.lazy" class="com.foo.AnotherBean"/></programlisting> |
|
|
|
<para>When the preceding configuration is consumed by an |
|
<interfacename>ApplicationContext</interfacename>, the bean named |
|
<literal>lazy</literal> is not eagerly pre-instantiated when the |
|
<interfacename>ApplicationContext</interfacename> is starting up, whereas |
|
the <literal>not.lazy</literal> bean is eagerly pre-instantiated.</para> |
|
|
|
<para>However, when a lazy-initialized bean is a dependency of a singleton |
|
bean that is <emphasis>not</emphasis> lazy-initialized, the |
|
<interfacename>ApplicationContext</interfacename> creates the |
|
lazy-initialized bean at startup, because it must satisfy the singleton's |
|
dependencies. The lazy-initialized bean is injected into a singleton bean |
|
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><beans/></literal> element; for example:</para> |
|
|
|
<programlisting language="xml"><beans default-lazy-init="true"> |
|
<lineannotation><!-- no beans will be pre-instantiated... --></lineannotation> |
|
</beans></programlisting> |
|
</section> |
|
|
|
<section id="beans-factory-autowire"> |
|
<title>Autowiring collaborators</title> |
|
|
|
<!--I've moved around info and done a lot of editing/reformatting in this section, but nothing is missing.--> |
|
|
|
<para>The Spring container can <emphasis>autowire</emphasis> relationships |
|
between collaborating beans. You can allow Spring to resolve collaborators |
|
(other beans) automatically for your bean by inspecting the contents of |
|
the <interfacename>ApplicationContext</interfacename>. Autowiring has the |
|
following advantages:</para> |
|
|
|
<para><itemizedlist> |
|
<listitem> |
|
<para>Autowiring can significantly reduce the need to specify properties |
|
or constructor arguments. (Other mechanisms such as a bean template |
|
<link linkend="beans-child-bean-definitions">discussed elsewhere in |
|
this chapter</link> are also valuable in this regard.)</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Autowiring can update a configuration as your objects evolve. For |
|
example, if you need to add a dependency to a class, that dependency |
|
can be satisfied automatically without you needing to modify the |
|
configuration. Thus autowiring can be especially useful during |
|
development, without negating the option of switching to explicit |
|
wiring when the code base becomes more stable.</para> |
|
</listitem> |
|
</itemizedlist> When using XML-based configuration metadata<footnote> |
|
<para>See <xref linkend="beans-factory-collaborators"/></para> |
|
</footnote>, you specify autowire mode for a bean definition with the |
|
<literal>autowire</literal> attribute of the |
|
<literal><bean/></literal> element. The autowiring functionality has |
|
five modes. You specify autowiring <emphasis>per</emphasis> bean and thus |
|
can choose which ones to autowire.</para> |
|
|
|
<table id="beans-factory-autowiring-modes-tbl"> |
|
<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><para>(Default) No autowiring. Bean references must be |
|
defined via a <literal>ref</literal> element. Changing the default |
|
setting is not recommended for larger deployments, because |
|
specifying collaborators explicitly gives greater control and |
|
clarity. To some extent, it documents the structure of a |
|
system.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>byName</entry> |
|
|
|
<entry><para>Autowiring by property name. Spring looks for a bean |
|
with the same name as the property that needs to be autowired. For |
|
example, if a bean definition is set to autowire by name, and it |
|
contains a <emphasis>master</emphasis> property (that is, it has a |
|
<emphasis>setMaster(..)</emphasis> method), Spring looks for a |
|
bean definition named <literal>master</literal>, and uses it to |
|
set the property.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>byType</entry> |
|
|
|
<entry><para>Allows a property to be autowired if exactly one bean |
|
of the property type exists in the container. If more than one |
|
exists, a fatal exception is thrown, which indicates that you may |
|
not use <emphasis>byType</emphasis> autowiring for that bean. If |
|
there are no matching beans, nothing happens; the property is not |
|
set.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>constructor</entry> |
|
|
|
<entry><para>Analogous to <emphasis>byType</emphasis>, but applies |
|
to constructor arguments. If there is not exactly one bean of the |
|
constructor argument type in the container, a fatal error is |
|
raised.</para></entry> |
|
</row> |
|
|
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<para>With <emphasis>byType</emphasis> or <emphasis>constructor</emphasis> |
|
autowiring mode, you can wire arrays and typed-collections. In such cases |
|
<emphasis>all</emphasis> autowire candidates within the container that |
|
match the expected type are provided to satisfy the dependency. You can |
|
autowire strongly-typed Maps if the expected key type is |
|
<classname>String</classname>. An autowired Maps values will consist of |
|
all bean instances that match the expected type, and the Maps keys will |
|
contain the corresponding bean names.</para> |
|
|
|
<para>You can combine autowire behavior with dependency checking, which is |
|
performed after autowiring completes.</para> |
|
|
|
<section id="beans-autowired-exceptions"> |
|
<title>Limitations and disadvantages of autowiring</title> |
|
|
|
<para>Autowiring works best when it is used consistently across a project. |
|
If autowiring is not used in general, it might be confusing to |
|
developers to use it to wire only one or two bean definitions.</para> |
|
|
|
<para>Consider the limitations and disadvantages of autowiring:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Explicit dependencies in <literal>property</literal> and |
|
<literal>constructor-arg</literal> settings always override |
|
autowiring. You cannot autowire so-called |
|
<emphasis>simple</emphasis> properties such as primitives, |
|
<classname>Strings</classname>, and <classname>Classes</classname> |
|
(and arrays of such simple properties). This limitation is |
|
by-design.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Autowiring is less exact than explicit wiring. Although, as |
|
noted in the above table, Spring is careful to avoid guessing in |
|
case of ambiguity that 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> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Multiple bean definitions within the container may match the |
|
type specified by the setter method or constructor argument to be |
|
autowired. For arrays, collections, or Maps, this is not necessarily |
|
a problem. However for dependencies that expect a single value, this |
|
ambiguity is not arbitrarily resolved. If no unique bean definition |
|
is available, an exception is thrown.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<para>In the latter scenario, you have several options:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Abandon autowiring in favor of explicit wiring.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Avoid autowiring for a bean definition by setting its |
|
<literal>autowire-candidate</literal> attributes to |
|
<literal>false</literal> as described in the next section.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Designate a single bean definition as the |
|
<emphasis>primary</emphasis> candidate by setting the |
|
<literal>primary</literal> attribute of its |
|
<literal><bean/></literal> element to |
|
<literal>true</literal>.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>If you are using Java 5 or later, implement the more |
|
fine-grained control available with annotation-based configuration, |
|
as described in <xref linkend="beans-annotation-config"/>.</para> |
|
</listitem> |
|
</itemizedlist> |
|
</section> |
|
|
|
<section id="beans-factory-autowire-candidate"> |
|
<title>Excluding a bean from autowiring</title> |
|
|
|
<para>On a per-bean basis, you can exclude a bean from autowiring. In |
|
Spring's XML format, set the <literal>autowire-candidate</literal> |
|
attribute of the <literal><bean/></literal> element to |
|
<literal>false</literal>; the container makes that specific bean |
|
definition unavailable to the autowiring infrastructure (including |
|
annotation style configurations such as <link |
|
linkend="beans-autowired-annotation" |
|
><interfacename>@Autowired</interfacename></link>).</para> |
|
|
|
<para>You can also limit autowire candidates based on pattern-matching |
|
against bean names. The top-level <literal><beans/></literal> |
|
element accepts one or more patterns within its |
|
<literal>default-autowire-candidates</literal> attribute. For example, |
|
to limit autowire candidate status to any bean whose name ends with |
|
<emphasis>Repository,</emphasis> provide a value of *Repository. To |
|
provide multiple patterns, define them in a comma-separated list. An |
|
explicit value of <literal>true</literal> or <literal>false</literal> |
|
for a bean definitions <literal>autowire-candidate</literal> attribute |
|
always takes precedence, and for such beans, the pattern matching rules |
|
do not apply.</para> |
|
|
|
<para>These techniques are useful for beans that you never want to be |
|
injected into other beans by autowiring. It does not mean that an |
|
excluded bean cannot itself be configured using autowiring. Rather, the |
|
bean itself is not a candidate for autowiring other beans.</para> |
|
|
|
<!--Last paragraph unclear to me. Is my edit ok? Revise as necessary.--> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-method-injection"> |
|
<title>Method injection</title> |
|
|
|
<para>In most application scenarios, most beans in the container are <link |
|
linkend="beans-factory-scopes-singleton">singletons</link>. When a |
|
singleton bean needs to collaborate with another singleton bean, or a |
|
non-singleton bean needs to collaborate with another non-singleton bean, |
|
you typically handle the dependency by defining one bean as a property of |
|
the other. A problem arises when the bean lifecycles are different. |
|
Suppose singleton bean A needs to use non-singleton (prototype) bean B, |
|
perhaps on each method invocation on A. The container only creates the |
|
singleton bean A once, and thus only gets one opportunity to set the |
|
properties. The container cannot provide bean A with a new instance of |
|
bean B every time one is needed.</para> |
|
|
|
<para>A solution is to forego some inversion of control. You can <link |
|
linkend="beans-factory-aware">make bean A aware of the container</link> by |
|
implementing the <interfacename>ApplicationContextAware</interfacename> |
|
interface, and by <link linkend="beans-factory-client">making a |
|
getBean("B") call to the container</link> ask for (a typically new) bean B |
|
instance every time bean A needs it. The following is an example of this |
|
approach:</para> |
|
|
|
<programlisting language="java"><lineannotation>// a class that uses a stateful Command-style class to perform some processing</lineannotation> |
|
package fiona.apple; |
|
|
|
<lineannotation>// Spring-API imports</lineannotation> |
|
import org.springframework.beans.BeansException; |
|
import org.springframework.context.Applicationcontext; |
|
import org.springframework.context.ApplicationContextAware; |
|
|
|
public class CommandManager implements ApplicationContextAware { |
|
|
|
private ApplicationContext applicationContext; |
|
|
|
public Object process(Map commandState) { |
|
<lineannotation>// grab a new instance of the appropriate <interfacename>Command</interfacename></lineannotation> |
|
Command command = createCommand(); |
|
<lineannotation>// set the state on the (hopefully brand new) <interfacename>Command</interfacename> instance</lineannotation> |
|
command.setState(commandState); |
|
return command.execute(); |
|
} |
|
|
|
protected Command createCommand() { |
|
<lineannotation>// notice the Spring API dependency!</lineannotation> |
|
return this.applicationContext.getBean("command", Command.class); |
|
} |
|
|
|
public void setApplicationContext(ApplicationContext applicationContext) |
|
throws BeansException { |
|
this.applicationContext = applicationContext; |
|
} |
|
}</programlisting> |
|
|
|
<para>The preceding is not desirable, because the business code is aware of |
|
and coupled to the Spring Framework. Method Injection, a somewhat advanced |
|
feature of the Spring IoC container, allows this use case to be handled in |
|
a clean |
|
fashion.<!--Why give an example that is not desirable? Unclear whether this is an illustration of true method injection.--></para> |
|
|
|
<sidebar> |
|
<para>You can read more about the motivation for Method Injection in |
|
<ulink url="http://blog.springsource.com/2004/08/06/method-injection/" |
|
>this blog entry</ulink>.</para> |
|
</sidebar> |
|
|
|
<section id="beans-factory-lookup-method-injection"> |
|
<title>Lookup method injection</title> |
|
|
|
<!--Deleted a box here that doesn't seem to have much info; I moved the blog entry link above. --> |
|
|
|
<para>Lookup method injection is the ability of the container to override |
|
methods on <emphasis>container managed beans</emphasis>, to return the |
|
lookup result for another named bean in the container. The lookup |
|
typically involves a prototype bean as in the scenario described in the |
|
preceding section. The Spring Framework implements this method injection |
|
by using bytecode generation from the CGLIB library to generate |
|
dynamically a subclass that overrides the |
|
method.<!--Note was plain text; I made it a note and moved it up.--></para> |
|
|
|
<note> |
|
<para>For this dynamic subclassing to work, you must have the CGLIB |
|
jar(s) in your classpath. The class that the Spring container will |
|
subclass cannot be <literal>final</literal>, and the method to be |
|
overridden cannot be <literal>final</literal> either. Also, testing a |
|
class that has an <literal>abstract</literal> method requires you to |
|
subclass the class yourself and to supply a stub implementation of the |
|
<literal>abstract</literal> method. Finally, objects that have been |
|
the target of method injection cannot be serialized.</para> |
|
</note> |
|
|
|
<para>Looking at the <classname>CommandManager</classname> class in the |
|
previous code snippet, you see that the Spring container will |
|
dynamically override the implementation of the |
|
<methodname>createCommand()</methodname> method. Your |
|
<classname>CommandManager</classname> class will not have any Spring |
|
dependencies, as can be seen in the reworked example:</para> |
|
|
|
<programlisting language="java">package fiona.apple; |
|
|
|
<lineannotation>// no more Spring imports! </lineannotation> |
|
|
|
public abstract class CommandManager { |
|
|
|
public Object process(Object commandState) { |
|
<lineannotation>// grab a new instance of the appropriate <interfacename>Command</interfacename> interface</lineannotation> |
|
Command command = createCommand(); |
|
<lineannotation>// set the state on the (hopefully brand new) <interfacename>Command</interfacename> instance</lineannotation> |
|
command.setState(commandState); |
|
return command.execute(); |
|
} |
|
|
|
<lineannotation>// okay... but where is the implementation of this method?</lineannotation> |
|
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="xml"><public|protected> [abstract] <return-type> theMethodName(<lineannotation>no-arguments</lineannotation>);</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. For example:</para> |
|
|
|
<programlisting language="xml"><lineannotation><!-- a stateful bean deployed as a prototype (non-singleton) --></lineannotation> |
|
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype"> |
|
<lineannotation><!-- inject dependencies here as required --></lineannotation> |
|
</bean> |
|
|
|
<lineannotation><!-- <literal>commandProcessor</literal> uses <literal>statefulCommandHelper</literal> --></lineannotation> |
|
<bean id="commandManager" class="fiona.apple.CommandManager"> |
|
<lookup-method name="createCommand" bean="command"/> |
|
</bean></programlisting> |
|
|
|
<para>The bean identified as <emphasis>commandManager</emphasis> calls its |
|
own method <methodname>createCommand()</methodname> whenever it needs a |
|
new instance of the <emphasis>command</emphasis> bean. You must be |
|
careful to deploy the <literal>command</literal> bean as a prototype, if |
|
that is actually what is needed. If it is deployed as a <link |
|
linkend="beans-factory-scopes-singleton">singleton</link>, the same |
|
instance of the <literal>command</literal> bean is returned each |
|
time.</para> |
|
|
|
<tip> |
|
<para>The interested reader may also find the |
|
<classname>ServiceLocatorFactoryBean</classname> (in the |
|
<literal>org.springframework.beans.factory.config</literal> package) |
|
to be of use. The approach used in ServiceLocatorFactoryBean is |
|
similar to that of another utility class, |
|
<classname>ObjectFactoryCreatingFactoryBean</classname>, but it allows |
|
you to specify your own lookup interface as opposed to a |
|
Spring-specific lookup interface. Consult the JavaDocs for these |
|
classes as well as this <ulink |
|
url="http://blog.arendsen.net/index.php/2006/10/05/on-the-servicelocatorfactorybean-dlas-and-the-sustainability-of-code-and-design/" |
|
>blog entry</ulink> for additional information |
|
ServiceLocatorFactoryBean.</para> |
|
</tip> |
|
</section> |
|
|
|
<section id="beans-factory-arbitrary-method-replacement"> |
|
<title>Arbitrary method replacement</title> |
|
|
|
<para>A less useful form of method injection than lookup method Injection |
|
is the ability to replace arbitrary methods in a managed bean with |
|
another method implementation. Users may safely skip the rest of this |
|
section until the functionality is actually |
|
needed.<!--Delete this section? See preceding sentence.--></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 bean. Consider the following |
|
class, with a method computeValue, which we want to override:</para> |
|
|
|
<programlisting language="java">public class MyValueCalculator { |
|
|
|
public String computeValue(String input) { |
|
<lineannotation>// some real code...</lineannotation> |
|
} |
|
|
|
<lineannotation>// some other methods...</lineannotation> |
|
|
|
}</programlisting> |
|
|
|
<para>A class implementing the |
|
<interfacename>org.springframework.beans.factory.support.MethodReplacer</interfacename> |
|
interface provides the new method definition.</para> |
|
|
|
<programlisting language="java"><lineannotation>/** meant to be used to override the existing <methodname>computeValue(String)</methodname> |
|
implementation in <classname>MyValueCalculator</classname> |
|
*/</lineannotation> |
|
public class ReplacementComputeValue implements MethodReplacer { |
|
|
|
public Object reimplement(Object o, Method m, Object[] args) throws Throwable { |
|
<lineannotation>// get the input value, work with it, and return a computed result</lineannotation> |
|
String input = (String) args[0]; |
|
... |
|
return ...; |
|
} |
|
}</programlisting> |
|
|
|
<para>The bean definition to deploy the original class and specify the |
|
method override would look like this:</para> |
|
|
|
<programlisting language="xml"><bean id="myValueCalculator" class="x.y.z.MyValueCalculator"> |
|
|
|
<lineannotation><!-- arbitrary method replacement --></lineannotation> |
|
<replaced-method name="computeValue" replacer="replacementComputeValue"> |
|
<arg-type>String</arg-type> |
|
</replaced-method> |
|
</bean> |
|
|
|
<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/></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 necessary only 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 |
|
<classname>java.lang.String</classname>:</para> |
|
|
|
<programlisting language="java"> java.lang.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 type only the shortest string that will match an |
|
argument type.</para> |
|
</section> |
|
</section> |
|
</section>
|
|
|