mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
92500ab902
CGLIB 3 has been released in order to depend on ASM 4, which Spring now depends on internally (see previous commit). This commit eliminates spring-beans' optional dependency on cglib-nodep v2.2 and instead repackages net.sf.cglib => org.springframework.cglib much in the same way we have historically done with ASM. This change is beneficial to users in several ways: - Eliminates the need to manually add CGLIB to the application classpath; especially important for the growing number of @Configuration class users. Java-based configuration functionality, along with proxy-target-class and method injection features now work 'out of the box' in Spring 3.2. - Eliminates the possibility of conflicts with other libraries that may dependend on differing versions of CGLIB, e.g. Hibernate 3.3.1.ga and its dependency on CGLIB 2.1.3 would easily cause a conflict if the application were depending on CGLIB 3 for Spring-related purposes. - Picks up CGLIB 3's changes to support ASM 4, meaning that CGLIB is that much less likely to work well in a Java 7 environment due to ASM 4's support for transforming classes with invokedynamic bytecode instructions. On CGLIB and ASM: CGLIB's own dependency on ASM is also transformed along the way to depend on Spring's repackaged org.springframework.asm, primarily to eliminate unnecessary duplication of ASM classfiles in spring-core and in the process save around 100K in the final spring-core JAR file size. It is coincidental that spring-core and CGLIB currently depend on the exact same version of ASM (4.0), but it is also unlikely to change any time soon. If this change does occur and versions of ASM drift, then the size optimization mentioned above will have to be abandoned. This would have no compatibility impact, however, so this is a reasonable solution now and for the forseeable future. On a mysterious NoClassDefFoundError: During the upgrade to CGLIB 3.0, Spring test cases began failing due to NoClassDefFoundErrors being thrown from CGLIB's DebuggingClassWriter regarding its use of asm-util's TraceClassVisitor type. previous versions of cglib-nodep, particularly 2.2, did not cause this behavior, even though cglib-nodep has never actually repackaged and bundled asm-util classes. The reason for these NoClassDefFoundErrors occurring now is still not fully understood, but appears to be due to subtle JVM bytecode preverification rules. The hypothesis is that due to minor changes in DebuggingClassWriter such as additional casts, access to instance variables declared in the superclass, and indeed a change in the superclass hierarchy, preverification may be kicking in on the toByteArray method body, at which point the reference to the missing TraceClassVisitor type is noticed and the NCDFE is thrown. For this reason, a dummy implementation of TraceClassVisitor has been added to spring-core in the org.springframework.asm.util package. This class simply ensures that Spring's own tests never result in the NCDFE described above, and more importantly that Spring's users never encounter the same. Other changes include: - rename package-private Cglib2AopProxy => CglibAopProxy - eliminate all 'cglibAvailable' checks, warnings and errors - eliminate all 'CGLIB2' language in favor of 'CGLIB' - eliminate all mention in reference and java docs of needing to add cglib(-nodep) to one's application classpath Issue: SPR-9669
1654 lines
80 KiB
XML
1654 lines
80 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<section xmlns="http://docbook.org/ns/docbook" version="5.0"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
|
xml: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 id="beans-dependency-resolution">
|
|
<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">InitializingBean
|
|
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 id="beans-collection-merge-limitations">
|
|
<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:c="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, 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. As of Spring
|
|
3.2 it is no longer necessary to add CGLIB to your classpath, because
|
|
CGLIB classes are repackaged under org.springframework and distributed
|
|
within the spring-core JAR. This is done both for convenience as well
|
|
as to avoid potential conflicts with other projects that use differing
|
|
versions of CGLIB.</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>
|