您的位置:首页 > 编程语言 > Java开发

Configuring Beans in the Spring IoC Container

2016-02-10 11:39 543 查看

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: