Content Table

Component Scan

使用 <context:component-scan> 特性,可以自动扫描 base-package 下类名有注解 @Component@Service 或者 @Controller 的类,为其在 Spring 容易里创建一个对象。

@Service@Controller@Component 在语法上作用是一样的,区别是各自有自己的语义,例如 SpringMVC 里用 @Controller 表明类是 Controller

Property Placeholder

properties 文件里定义 key | value,然后在 Bean Configuration File 里用 ${key} 引用 key 对应的值。

Bean Configuration File 里使用 <context:property-placeholder> 引入 properties 文件。

现在很多时候都使用 Gradle 的资源替换来代替了。

多个配置文件

把 Spring 的 Bean Configuration File 根据模块分散到不同的文件里,便于管理,然后使用 <import> 把它们组织在一起。例如:

Bean Bean Configuration File
user spring-beans.xml
address spring-beans-1.xml
customer spring-beans-2.xml

在 spring-beans.xml 里 import spring-beans-1.xml and spring-beans-2.xml,然后 Spring Context 加载 spring-beans.xml。

Bean 在配置文件中定义的顺序任意,其实最后就是把所有的配置文件和成一个大的配置文件,然后在解析创建对象,所以就像在单一的配置文件里定义 Bean 一样顺序不重要。

Property Editor

在设置一个对象类型的属性时:

  1. 使用 ref 引用已经存在的对象
  2. 使用 bean 标签创建一个匿名对象
  3. 还有一种方式是给 value 赋值一个字符串,Spring 自动的把这个字符串转换为对象

第三种方式的实现需要以下几步:

  1. 需要提供一个把 String 转换为对象的类,称之为自定义编辑器(CustomEditor)
  2. 然后把这个自定义编辑器注册到 Spring Container
  3. 使用字符串配置对象属性

FactoryBean

FactoryBean 是用来创建 Bean 的工厂,实现 FactoryBean 接口 的类就可以用来创建其他 Bean 了,在 Bean Configuration File 里的 <bean> 里定义要生成的 Bean。

FactoryBean 命名规范:Bean 的类名 后跟着 FactoryBean,例如创建 User 的 FactoryBean 的类名应该为 UserFactoryBean。

如果 Bean 的创建不只是简单的 setter, constructor 注入,而是有其他的逻辑,这个时候就可以用 FactoryBean 来创建 Bean(有点像同时用了 Factory Pattern 和 Builder Pattern)。

FactoryBean 是很常见的,例如 Spring 集成 MyBatis 时用 SqlSessionFactoryBean 来创建 SqlSession。

MapFactoryBean 注入 Map

1
2
3
4
5
6
7
8
9
<bean id="mapExample" class="com.xtuer.beans.CollectionHolder">
<property name="map">
<map> <!--表示是 map-->
<entry key="German" value="Gut"/>
<entry key="English" value="Good"/>
<entry key="Chinese" value="没问题"/>
</map>
</property>
</bean>

上面的方式注入 Map,Map 的类型不受我们控制,默认是 java.util.LinkedHashMap。MapFactoryBean 可以创建一个特定类型的 Map。由于 MapFactoryBean 的配置太过麻烦,这里我们只结束和其等效的 <util:map>

SetFactoryBean 注入 Set

1
2
3
4
5
6
7
8
9
<bean id="setExample" class="com.xtuer.beans.CollectionHolder">
<property name="set">
<set> <!--表示是 set-->
<value>Gut</value>
<value>Good</value>
<value>没问题</value>
</set>
</property>
</bean>

上面的方式注入 Set,Set 的类型不受我们控制,默认是 java.util.LinkedHashSet。SetFactoryBean 可以创建一个特定类型的 Set。由于 SetFactoryBean 的配置太过麻烦,这里我们只结束和其等效的 <util:set>

ListFactoryBean 注入 List

1
2
3
4
5
6
7
8
9
<bean id="listExample" class="com.xtuer.beans.CollectionHolder">
<property name="list">
<list> <!--表示是 list-->
<value>Gut</value>
<value>Good</value>
<value>没问题</value>
</list>
</property>
</bean>

上面的方式注入 List,List 的类型不受我们控制,默认是 java.util.ArrayList。ListFactoryBean 可以创建一个特定类型的 List。由于 ListFactoryBean 的配置太过麻烦,这里我们只介绍和其等效的 <util:list>

List, Set, Map, Properties 注入

注入 List

1
2
3
4
5
6
7
8
9
<bean id="listExample" class="com.xtuer.beans.CollectionHolder">
<property name="list">
<list> <!--表示是 list-->
<value>Gut</value>
<value>Good</value>
<value>没问题</value>
</list>
</property>
</bean>

<list> 里不只是可以使用 <value>,还可以使用 <ref bean=""><bean class="ClassName">,如下

1
2
3
4
5
6
7
8
9
10
11
12
<bean id="listExample" class="com.xtuer.beans.CollectionHolder">
<property name="list">
<list> <!--表示是 list-->
<value>Gut</value>
<value>Good</value>
<value>没问题</value>

<ref bean="user"/>
<bean class="com.xtuer.beans.User"/>
</list>
</property>
</bean>

Contructor 注入

演示怎么给构造函数注入参数,使用指定的构造函数创建对象。

Customer

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.xtuer.beans;

public class Customer {
private String name;
private int age;
private String telephone;

public Customer(String name, int age) {
this.name = name;
this.age = age;
}

public Customer(String name, String telephone, int age) {
this.name = name;
this.telephone = telephone;
this.age = age;
}

public Customer(String name, int age, String telephone) {
this.name = name;
this.telephone = telephone;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getTelephone() {
return telephone;
}

public void setTelephone(String telephone) {
this.telephone = telephone;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}