Configuring Beans in the Spring IoC Container

Configuring Beans in the Spring IoC Container


这本书对spring bean的配置比较全面。
注:配置类似
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
的时候,xsd的版本号不要带,至于为什么,参考以前转载的老外博客。

Problem

Spring offers a powerful IoC container to manage the beans that make up an application. To utilize the
container services, you have to configure your beans to run in the Spring IoC container.

Solution

You can configure your beans in the Spring IoC container through XML files, properties files,
annotations, or even APIs.
Spring allows you to configure your beans in one or more bean configuration files. For a
simple application, you can simply centralize your beans in a single configuration file. But for a large
application with a lot of beans, you should separate them in multiple configuration files according to
their functionalities. One useful division is by the architectural layer that a given context services.
How It Works
Suppose that you are going to develop an application for generating sequence numbers. In this
application, there may be many series of sequence numbers to generate for different purposes. Each
one of them will have its own prefix, suffix, and initial value. So, you have to create and maintain
multiple generator instances in your application.
Creating the Bean Class
In accordance with the requirements, you create the SequenceGenerator class that has three
properties_prefix, suffix, and initial_that can be injected via setter methods or a constructor. The
private field counter is for storing the current numeric value of this generator. Each time you call the
getSequence() method on a generator instance, you will get the last sequence number with the prefix
and suffix joined. You declare this method as synchronized to make it thread-safe.



package com.apress.springenterpriserecipes.sequence;
public class SequenceGenerator {
private String prefix;
private String suffix;
private int initial;
private int counter;
public SequenceGenerator() {}
public SequenceGenerator(String prefix, String suffix, int initial) {
this.prefix = prefix;
this.suffix = suffix;
this.initial = initial;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public void setInitial(int initial) {
this.initial = initial;
}
public synchronized String getSequence() {
StringBuffer buffer = new StringBuffer();
buffer.append(prefix);
buffer.append(initial + counter++);
buffer.append(suffix);
return buffer.toString();
}
}


As you see, this SequenceGenerator class can be configured by getters/setters or by the constructor.
When configuring them with the container, this is called constructor injection and setter injection.

Creating the Bean Configuration File

To declare beans in the Spring IoC container via XML, you first have to create an XML bean
configuration file with an appropriate name, such as beans.xml. You can put this file in the root
of the classpath for easier testing within an IDE.
The Spring configuration XML allows you to use custom tags from different schemas (tx, jndi, jee,
and so on) to make the bean configuration simpler and clearer. Here’s an example of the simplest XML
configuration possible.



<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
...
</beans>


Declaring Beans in the Bean Configuration File

Each bean should provide a unique name or id and a fully qualified class name for the Spring IoC
container to instantiate it. For each bean property of simple type (e.g., String and other primitive types),
you can specify a <value> element for it. Spring will attempt to convert your value into the declaring type
of this property. To configure a property via setter injection, you use the <property> element and specify
the property name in its name attribute. A <property> requires that the bean contain a corresponding
setter method.

<bean name="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
<property name="prefix">
<value>30</value>
</property>
<property name="suffix">
<value>A</value>
</property>
<property name="initial">
<value>100000</value>
</property>
</bean>


You can also configure bean properties via constructor injection by declaring them in the
<constructor-arg> elements. There’s not a name attribute in <constructor-arg> because constructor
arguments are position-based.


<bean name="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
<constructor-arg>
<value>30</value>
</constructor-arg>
<constructor-arg>
<value>A</value>
</constructor-arg>
<constructor-arg>
<value>100000</value>
</constructor-arg>
</bean>

In the Spring IoC container, each bean’s name should be unique, although duplicate names are
allowed for overriding bean declaration if more than one context is loaded. A bean’s name can be
defined by the name attribute of the <bean> element. Actually, there’s a preferred way of identifying a
bean: through the standard XML id attribute, whose purpose is to identify an element within an XML
document. In this way, if your text editor is XML-aware, it can help to validate each bean’s uniqueness at
design time.

<bean id="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
...
</bean>

However, XML has restrictions on the characters that can appear in the XML id attribute, but
usually you won’t use those special characters in a bean name. Moreover, Spring allows you to specify
multiple names, separated by commas, for a bean in the name attribute. But you can’t do so in the id
attribute because commas are not allowed there.
In fact, neither the bean name nor the bean ID is required for a bean. A bean that has no name
defined is called an anonymous bean. You will usually create beans like this that serve only to interact
with the Spring container itself; that you are sure you will only inject by type later on; or that you will
nest, inline, in the declaration of an outer bean.

Defining Bean Properties by Shortcut

Spring supports a shortcut for specifying the value of a simple type property. You can present a value
attribute in the <property> element instead of enclosing a <value> element inside.


<bean id="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
<property name="prefix" value="30" />
<property name="suffix" value="A" />
<property name="initial" value="100000" />
</bean>
This shortcut also works for constructor arguments.
<bean name="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
<constructor-arg value="30" />
<constructor-arg value="A" />
<constructor-arg value="100000" />
</bean>

Spring 2.0 provides another convenient shortcut for you to define properties. It’s by using the p
schema to define bean properties as attributes of the <bean> element. This can shorten the lines of XML
configuration.

<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">
<span style="font-family: TheSansMonoCondensed-Plain; font-size: 9pt;"><bean id="sequenceGenerator"
<span style="font-size: 9pt;">class="com.apress.springenterpriserecipes.sequence.SequenceGenerator"
<span style="font-family: TheSansMonoCondensed-Black; font-size: 9pt;">p:prefix="30" p:suffix="A" p:initial="100000" />
<span style="font-family: TheSansMonoCondensed-Plain; font-size: 9pt;"></beans></span></span></span><br style="orphans: 2; text-align: -webkit-auto; widows: 2;" /></span>

Configuring Collections for Your Beans

List, Set, and Map are the core interfaces representing three main types of collections. For each
collection type, Java provides several implementations with different functions and characteristics from
which you can choose. In Spring, these types of collections can be easily configured with a group of
built-in XML tags, such as <list>, <set>, and <map>.
Suppose you are going to allow more than one suffix for your sequence generator. The suffixes will
be appended to the sequence numbers with hyphens as the separators. You may consider accepting
suffixes of arbitrary data types and converting them into strings when appending to the sequence
numbers.
Lists, Arrays, and Sets
First, let’s use a java.util.List collection to contain your suffixes. A list is an ordered and indexed
collection whose elements can be accessed either by index or with a for-each loop.
 
package com.apress.springenterpriserecipes.sequence;
...
public class SequenceGenerator {
...
private List<Object> suffixes;
public void setSuffixes(List<Object> suffixes) {
this.suffixes = suffixes;
}
public void setPrefixGenerator(PrefixGenerator prefixGenerator) {
this.prefixGenerator = prefixGenerator;
}
public synchronized String getSequence() {
StringBuffer buffer = new StringBuffer();
...
for (Object suffix : suffixes) {
buffer.append("-");
buffer.append(suffix);
}
return buffer.toString();
}
}

To define a property of the interface java.util.List in the bean configuration, you specify a <list>
tag that contains the elements. The elements allowed inside the <list> tag can be a simple constant
value specified by
<value>, a bean reference by <ref>, an inner bean definition by <bean>, or a null
element by <null>. You can even embed other collections in a collection.


<bean id="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
<property name="prefixGenerator" ref="datePrefixGenerator" />
<property name="initial" value="100000" />
<property name="suffixes">
<list>
<value>A</value>
<bean class="java.net.URL">
<constructor-arg value="http" />
<constructor-arg value="www.apress.com" />
<constructor-arg value="/" />
</bean>
<null />
</list>
</property>
</bean>


Conceptually, an array is very similar to a list in that it’s also an ordered and indexed collection that
can be accessed by index. The main difference is that the length of an array is fixed and cannot be
extended dynamically. In the Java Collections framework, an array and a list can be converted to each
other through the Arrays.asList() and List.toArray() methods. For your sequence generator, you can
use an Object[] array to contain the suffixes and access them either by index or with a for-each loop.


package com.apress.springenterpriserecipes.sequence;
...
public class SequenceGenerator {
...
private Object[] suffixes;
public void setSuffixes(Object[] suffixes) {
this.suffixes = suffixes;
}
...
}

The definition of an array in the bean configuration file is identical to a list denoted by the
<list> tag.
Another common collection type is a set. Both the java.util.List interface and the java.util.Set
interface extend the same interface: java.util.Collection. A set differs from a list in that it is neither
ordered nor indexed, and it can store unique objects only. That means no duplicate element can be
contained in a set. When the same element is added to a set for the second time, it will replace the old
one. The equality of elements is determined by the equals() method.
package com.apress.springenterpriserecipes.sequence;


   package com.apress.springenterpriserecipes.sequence;
...
public class SequenceGenerator {
...
private Set<Object> suffixes;
public void setSuffixes(Set<Object> suffixes) {
this.suffixes = suffixes;
}
...
}

To define a property of java.util.Set type, use the <set> tag to define the elements in the same way
as a list.


<bean id="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
...
<property name="suffixes">
<set>
<value>A</value>
<bean class="java.net.URL">
<constructor-arg value="http" />
<constructor-arg value="www.apress.com" />
<constructor-arg value="/" />
</bean>
<null />
</set>
</property>
</bean>


Although there’s not an order concept in the original set semantics, Spring preserves the order of
your elements by using
java.util.LinkedHashSet, an implementation of the java.util.Set interface
that does preserve element order.

Maps and Properties

A map is a table that stores its entries in key/value pairs. You can get a particular value from a map by its
key, and also iterate the map entries with a for-each loop. Both the keys and values of a map can be of
arbitrary type. Equality between keys is also determined by the equals() method. For example, you can
modify your sequence generator to accept a java.util.Map collection that contains suffixes with keys.



package com.apress.springenterpriserecipes.sequence;
...
public class SequenceGenerator {
...
private Map<Object, Object> suffixes;
public void setSuffixes(Map<Object, Object> suffixes) {
this.suffixes = suffixes;
}
public synchronized String getSequence() {
StringBuffer buffer = new StringBuffer();
...
for (Map.Entry entry : suffixes.entrySet()) {
buffer.append("-");
buffer.append(entry.getKey());
buffer.append("@");
buffer.append(entry.getValue());
}
return buffer.toString();
}
}

In Spring, a map is defined by the <map> tag, with multiple <entry> tags as children. Each entry
contains a key and a value. The key must be defined inside the
<key> tag. There is no restriction on the
type of the key and value, so you are free to specify a
<value>, <ref>, <bean>, <idref>, or <null> element
for them. Spring will also preserve the order of the map entries by using java.util.LinkedHashMap.


<bean id="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
...
<property name="suffixes">
<map>
<entry>
<key>
<value>type</value>
</key>
<value>A</value>
</entry>
<entry>
<key>
<value>url</value>
</key>
<bean class="java.net.URL">
<constructor-arg value="http" />
<constructor-arg value="www.apress.com" />
<constructor-arg value="/" />
</bean>
</entry>
</map>
</property>
</bean>

There are shortcuts to defining map keys and values as attributes of the <entry> tag. If they are
simple constant values, you can define them by
key and value. If they are bean references, you can
define them by
key-ref and value-ref.


<pre name="code" class="html"><bean id="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
...
<property name="suffixes">
<map>
<entry key="type" value="A" />
<entry key="url">
<bean class="java.net.URL">
<constructor-arg value="http" />
<constructor-arg value="www.apress.com" />
<constructor-arg value="/" />
</bean>
</entry>
</map>
</property>
</bean>


 

In all the collection classes seen thus far, you used values to set the properties. Sometimes the
desired goal is to configure a null value using a Map instance. Spring’s XML configuration schema
includes explicit support for this. Here is a map with null values for the value of an entry:


<property name="nulledMapValue">
<map>
<entry>
<key> <value>null</value> </key>
</entry>
</map>
</property>

A java.util.Properties collection is very similar to a map. It also implements the java.util.Map
interface and stores entries in key/value pairs. The only difference is that the keys and values of a
Properties collection are always strings.

package com.apress.springenterpriserecipes.sequence;
...
public class SequenceGenerator {
...
private Properties suffixes;
public void setSuffixes(Properties suffixes) {
this.suffixes = suffixes;
}
...
}

To define a java.util.Properties collection in Spring, use the <props> tag with multiple <prop> tags
as children. Each <prop> tag must have a key attribute defined and the corresponding value enclosed.

<bean id="sequenceGenerator"
class="com.apress.springenterpriserecipes.sequence.SequenceGenerator">
...
<property name="suffixes">
<props>
<prop key="type">A</prop>
<prop key="url">http://www.apress.com/</prop>
<prop key="null">null</prop>
</props>
</property>
</bean>

If you define your beans with inheritance, a child bean’s collection can be merged with that of its
parent by setting the
merge attribute to true. For a <list> collection, the child elements will be added.

来源:

Spring Enterprise Recipes: A Problem-Solution Approach  2016年2月10


Copyright © 2009 by Gary Mak and Josh Long


All rights reserved. No part of this work may be reproduced or transmitted in any form or by any


means, electronic or mechanical, including photocopying, recording, or by any information


storage or retrieval system, without the prior written permission of the copyright owner and the


publisher.


ISBN-13 (pbk): 978-1-4302-2497-6


ISBN-13 (electronic): 978-1-4302-2498-3


Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dreamer who

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值