# 详细的依赖关系和配置

如前一节所述,您可以将 bean 属性和构造函数参数定义为对其他托管 bean(协作者)的引用或内联定义的值。Spring 基于 XML 的配置元数据支持其 <property/><constructor arg/>元素中的子元素类型。

# 字面量值

<property/>元素的 value 属性将属性或构造函数参数指定为人类可读的字符串表示形式。Spring 的 转换服务 (opens new window) 用于将这些值从字符串转换为属性或参数的实际类型。以下示例显示了正在设置的各种值:\

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- setDriverClassName(String) 方法将被调用 -->
    <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="misterkaoli"/>
</bean>
1
2
3
4
5
6
7

以下示例使用 p-namespace (opens new window) 进行更简洁的 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
    https://www.springframework.org/schema/beans/spring-beans.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="misterkaoli"/>

</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

前面的 XML 更简洁。但是,拼写错误是在运行时而不是设计时发现的,除非您在创建 bean 定义时使用支持自动属性完成的 IDE(例如 IntelliJ IDEA (opens new window)Spring Tools for Eclipse )。 (opens new window)强烈推荐这种 IDE 帮助。

您还可以配置 java.util.Properties 实例,如下所示:

<bean id="mappings"
    class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">

    <!-- java.util.Properties -->
    <property name="properties">
        <value>
            jdbc.driver.className=com.mysql.jdbc.Driver
            jdbc.url=jdbc:mysql://localhost:3306/mydb
        </value>
    </property>
</bean>
1
2
3
4
5
6
7
8
9
10
11

Spring 容器将 <value/>元素中的文本转换为 java.util.Properties属性实例,使用 JavaBeans PropertyEditor 机制。这是一个很好的快捷方式,也是 Spring 团队喜欢使用嵌套的 <value/>元素而不是 value 属性样式的几个地方之一。

# 内部 Bean

<bean id="outer" class="...">
    <!-- 不要使用对目标 bean 的引用,只需内联定义目标 bean 即可  -->
    <property name="target">
        <bean class="com.example.Person"> <!-- 这个是 inner bean -->
            <property name="name" value="Fiona Apple"/>
            <property name="age" value="25"/>
        </bean>
    </property>
</bean>
1
2
3
4
5
6
7
8
9

内部 bean 定义不需要定义的 ID 或名称。如果指定,容器不会使用这样的值作为标识符。容器在创建时也会忽略该 scope 标志,因为内部 bean 始终是匿名的,并且始终使用外部 bean 创建。不可能独立访问内部 bean 或将它们注入到协作 bean 中,而不是注入封闭 bean。

# 集合

<list/><set/><map/><props/>元素分别设置 Java 集合类型 list、set、map 和properties 的属性和参数。以下示例显示了如何使用它们:

<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- setAdminEmails(java.util.Properties) 方法被调用 -->
    <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>
    <!-- setSomeList(java.util.List) 被调用 -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- setSomeMap(java.util.Map) 被调用 -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- setSomeSet(java.util.Set) 方法被调用 -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 强类型集合

public class SomeClass {

    private Map<String, Float> accounts;

    public void setAccounts(Map<String, Float> accounts) {
        this.accounts = accounts;
    }
}
1
2
3
4
5
6
7
8
<beans>
    <bean id="something" class="x.y.SomeClass">
        <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>
1
2
3
4
5
6
7
8
9
10
11

Spring 会将 value 转换为 Float 类型

# Null 和空字符串值

Spring 将属性等的空参数视为空字符串。以下基于 XML 的配置元数据片段将 email 属性设置为空字符串值("")。

<bean class="ExampleBean">
    <property name="email" value=""/>
</bean>
1
2
3

等效于

exampleBean.setEmail("");
1

<null/>元素处理 null 值。以下清单显示了一个示例:

exampleBean.setEmail(null);
1

# 复合属性名称

设置 bean 属性时,可以使用复合属性名或嵌套属性名,只要路径的所有组件(最终属性名除外)都不为null。考虑下面的 bean 定义:

<bean id="something" class="things.ThingOne">
    <property name="fred.bob.sammy" value="123" />
</bean>
1
2
3

表示在 ThingOne 中有一个属性 fred,fred 下面有一个属性 bob