1602 lines
77 KiB
XML
1602 lines
77 KiB
XML
<?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
|
|
has to be compiled with the debug flag enabled so that Spring can
|
|
lookup 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-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>
|