[04] Bean的实例化和多个配置文件
之前我们已经提到过,Spring的核心能力之一就是IOC机制,从上章的示例中我们也可以看到,Spring中的ApplicationContext充当了一个实例化对象的容器的角色,并管理着它们的生命周期。你只需要拿来就可以直接使用了。
那么这些Bean是如何实例化的呢?这一章接着之前Coder的示例,我们就来了解一下这个问题。
1、实例化方式
1.1 构造器方式
Spring默认的情况下是调用Java类的构造器进行初始化的,也就是说它调用了类默认的构造函数,我们试着显性地覆盖默认的构造函数,让它打印一些语句,然后重新执行一下程序:
public class Coder {
private String name;
private int age;
public Coder() {
System.out.println("This is the constructor with none-parameter");
}
public void print(){
System.out.println("Hello World");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
x
1
public class Coder {
2
private String name;
3
private int age;
4
5
public Coder() {
6
System.out.println("This is the constructor with none-parameter");
7
}
8
9
public void print(){
10
System.out.println("Hello World");
11
}
12
13
public String getName() {
14
return name;
15
}
16
17
public void setName(String name) {
18
this.name = name;
19
}
20
21
public int getAge() {
22
return age;
23
}
24
25
public void setAge(int age) {
26
this.age = age;
27
}
28
}
那么使用构造器方式,我们需要默认设置一些初始化的值,那么需要有对应的构造函数,以及在xml中进行对应的配置,那么配置的方式是利用<constructor-arg>标签,如下:
- 增加构造函数
- 增加xml中对应bean标签中的<constructor-arg>
public Coder(String name, int age) {
this.name = name;
this.age = age;
}
4
1
public Coder(String name, int age) {
2
this.name = name;
3
this.age = age;
4
}
<bean id="coder" class="dulk.learn.spring.Coder">
<constructor-arg index="0" value="Dulk"></constructor-arg>
<constructor-arg index="1" value="27"></constructor-arg>
</bean>
4
1
<bean id="coder" class="dulk.learn.spring.Coder">
2
<constructor-arg index="0" value="Dulk"></constructor-arg>
3
<constructor-arg index="1" value="27"></constructor-arg>
4
</bean>
顺便覆盖一下Coder的toString方法,在测试类中进行调用,我们就可以看到Bean的信息了:
1.2 静态工厂方式
即调用工厂类的静态方法来创建对象,并返回引用。配置文件中的bean标签,除了class属性,还需要用到"factory-method"属性,如下:
public class StaticFactory {
public static Coder produceCoder() {
System.out.println("invoke the produceCode() of StaticFactory");
return new Coder();
}
}
6
1
public class StaticFactory {
2
public static Coder produceCoder() {
3
System.out.println("invoke the produceCode() of StaticFactory");
4
return new Coder();
5
}
6
}
<bean id="coder" class="dulk.learn.spring.StaticFactory" factory-method="produceCoder"></bean>
1
1
<bean id="coder" class="dulk.learn.spring.StaticFactory" factory-method="produceCoder"></bean>
值得一提的是,尽管这里的静态工厂方法每次返回都使用了new关键字,但你多次获取Coder时却始终是同一个对象,也就是说,new Coder()调用一次之后,该实例化对象就作为单例存储在容器中了,每次获取的都是容器中的该对象,而不是重新实例化。事实上,构造器方式也是如此,Spring中管理Bean的默认方式就是单例模式。
1.3 普通工厂方式
普通工厂方式和静态工厂方式的区别就在于,普通工厂类需要你首先进行初始化,然后再调用其生产方法。这意味着,你在配置普通的对象之前,也要配置工厂类,交给Spring去管理,这里需要额外用到“factory-bean”属性。如下:
public class CustomFactory {
public Coder produceCoder() {
System.out.println("invoke the produceCode() of CustomFactory");
return new Coder();
}
}
6
1
public class CustomFactory {
2
public Coder produceCoder() {
3
System.out.println("invoke the produceCode() of CustomFactory");
4
return new Coder();
5
}
6
}
<bean id="customFactory" class="dulk.learn.spring.CustomFactory"></bean>
<bean id="coder" factory-bean="customFactory" factory-method="produceCoder"></bean>
2
1
<bean id="customFactory" class="dulk.learn.spring.CustomFactory"></bean>
2
<bean id="coder" factory-bean="customFactory" factory-method="produceCoder"></bean>
工厂类型的生产方式,主要在于可以提前封装一些信息,假如需要数据库连接对象,在工厂类中可以提前将连接信息(数据库连接账户密码等)封装进去,通过工厂类获取的对象可以直接使用。这时候若是使用new来获取新的对象,就无法达到如期的效果。
2、配置文件
Spring提供了import标签,可以在一个配置文件中引入其他Spring配置文件。这种往往在针对不同模块和团队分工合作上,起到了很好的划分作用。语法如下,其中{path}指引入配置文件的相对路径(相对于主配置文件):
<import resource="{path}" />
1
<import resource="{path}" />