- 内容提要
- 作者简介
- 译者简介
- 前言
- HTTP
- Servlet 和 JSP
- 下载 Spring 或使用 STS 与 Maven/Gradle
- 手动下载 Spring
- 使用 STS 和 Maven/Gradle
- 下载 Spring 源码
- 本书内容简介
- 下载示例应用
- 第 1 章Spring 框架
- 第 2 章模型 2 和 MVC 模式
- 第 3 章Spring MVC 介绍
- 第 4 章基于注解的控制器
- 第 5 章数据绑定和表单标签库
- 第 6 章转换器和格式化
- 第 7 章验证器
- 第 8 章表达式语言
- 第 9 章JSTL
- 第 10 章国际化
- 第 11 章上传文件
- 第 12 章下载文件
- 第 13 章应用测试
- 附录 A Tomcat
- 附录 B Spring Tool Suite 和 Maven
- 附录 C Servlet
- 附录 D JavaServer Pages
- 附录 E 部署描述符
1.2 Spring 控制反转容器的使用
本节主要介绍 Spring 如何管理 bean 和依赖关系。
1.2.1 通过构造器创建一个 bean 实例
前面已经介绍,通过调用 ApplicationContext 的 getBean 方法可以获取一个 bean 的实例。下面的配置文件中定义了一个名为 product 的 bean(见清单 1.1)。
清单 1.1 一个简单的配置文件
< ?xml version="1.0" encoding="UTF-8"?>
< 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.xsd">
< bean name="product" class="springintro.bean.Product"/>
< /beans>
该 bean 的定义告诉 Spring,通过默认无参的构造器来初始化 Product 类。如果不存在该构造器(如果类的编写者重载了构造器,且没有显示声明默认构造器),则 Spring 将抛出一个异常。此外,该无参数的构造器并不要求是 public 签名。
注意,应采用 id 或者 name 属性标识一个 bean。为了让 Spring 创建一个 Product 实例,应将 bean 定义的 name 值“product”(具体实践中也可以是 id 值)和 Product 类型作为参数传递给 ApplicationContext 的 getBean 方法。
ApplicationContext context =
new ClassPathXmlApplicationContext(
new String[] {"spring-config.xml"});
Product product1 = context.getBean("product", Product.class);
product1.setName("Excellent snake oil");
System.out.println("product1: " + product1.getName());
1.2.2 通过工厂方法创建一个 bean 实例
大部分类可以通过构造器来实例化。然而,Spring 还同样支持通过调用一个工厂的方法来初始化类。
下面的 bean 定义展示了通过工厂方法来实例化 java.time.LocalDate。
<bean id="localDate" class="java.time.LocalDate"
factory-method="now"/>
本例中采用了 id 属性而非 name 属性来标识 bean,采用了 getBean 方法来获取 LocalDate 实例。
ApplicationContext context =
new ClassPathXmlApplicationContext(
new String[] {"spring-config.xml"});
LocalDate localDate = context.getBean("localDate", LocalDate.class);
1.2.3 销毁方法的使用
有时,我们希望一些类在被销毁前能执行一些方法。Spring 考虑到了这样的需求。可以在 bean 定义中配置 destroy-method 属性,来指定在销毁前要执行的方法。
下面的例子中,我们配置 Spring 通过 java.util.concurrent.Executors 的静态方法 newCached ThreadPool 来创建一个 java.uitl.concurrent.ExecutorService 实例,并指定了 destroy-method 属性值为 shutdown 方法。这样,Spring 会在销毁 ExecutorService 实例前调用其 shutdown 方法。
<bean id="executorService" class="java.util.concurrent.Executors"
factory-method="newCachedThreadPool"
destroy-method="shutdown"/>
1.2.4 向构造器传递参数
Spring 支持通过带参数的构造器来初始化类(见清单 1.2)。
清单 1.2 Product 类
package springintro.bean;
import java.io.Serializable;
public class Product implements Serializable {
private static final long serialVersionUID = 748392348L;
private String name;
private String description;
private float price;
public Product() {
}
public Product(String name, String description, float price) {
this.name = name;
this.description = description;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
以下的定义展示了如何通过参数名传递参数。
<bean name="featuredProduct" class="springintro.bean.Product">
<constructor-arg name="name" value="Ultimate Olive Oil"/>
<constructor-arg name="description"
value="The purest olive oil on the market"/>
<constructor-arg name="price" value="9.95"/>
</bean>
这样,在创建 Product 实例时,Spring 会调用如下构造器:
public Product(String name, String description, float price) {
this.name = name;
this.description = description;
this.price = price;
}
除了通过名称传递参数外,Spring 还支持通过指数方式来传递参数,具体如下:
<bean name="featuredProduct2" class="springintro.bean.Product">
<constructor-arg index="0" value="Ultimate Olive Oil"/>
<constructor-arg index="1"
value="The purest olive oil on the market"/>
<constructor-arg index="2" value="9.95"/>
</bean>
需要说明的是,采用这种方式,对应构造器的所有参数必须传递,缺一不可。
1.2.5 Setter 方式依赖注入
下面以 Employee 类和 Address 类为例,介绍 setter 方式依赖注入(见清单 1.3 和清单 1.4)。
清单 1.3 Employee 类
package springintro.bean;
public class Employee {
private String firstName;
private String lastName;
private Address homeAddress;
public Employee() {
}
public Employee(String firstName, String lastName, Address
homeAddress) {
this.firstName = firstName;
this.lastName = lastName;
this.homeAddress = homeAddress;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Address getHomeAddress() {
return homeAddress;
}
public void setHomeAddress(Address homeAddress) {
this.homeAddress = homeAddress;
}
@Override
public String toString() {
return firstName + " " + lastName
+ "\n" + homeAddress;
}
}
清单 1.4 Address 类
package springintro.bean;
public class Address {
private String line1;
private String line2;
private String city;
private String state;
private String zipCode;
private String country;
public Address(String line1, String line2, String city,
String state, String zipCode, String country) {
this.line1 = line1;
this.line2 = line2;
this.city = city;
this.state = state;
this.zipCode = zipCode;
this.country = country;
}
// getters and setters omitted
@Override
public String toString() {
return line1 + "\n"
+ line2 + "\n"
+ city + "\n"
+ state + " " + zipCode + "\n"
+ country;
}
}
Employee 依赖于 Address 类,可以通过如下配置来保证每个 Employee 实例都能包含 Address 实例。
<bean name="simpleAddress" class="springintro.bean.Address">
<constructor-arg name="line1" value="151 Corner Street"/>
<constructor-arg name="line2" value=""/>
<constructor-arg name="city" value="Albany"/>
<constructor-arg name="state" value="NY"/>
<constructor-arg name="zipCode" value="99999"/>
<constructor-arg name="country" value="US"/>
</bean>
<bean name="employee1" class="springintro.bean.Employee">
<property name="homeAddress" ref="simpleAddress"/>
<property name="firstName" value="Junior"/>
<property name="lastName" value="Moore"/>
</bean>
simpleAddress 对象是 Address 类的一个实例,它通过构造器方式实例化。employee1 对象则通过配置 property 元素来调用 setter 方法以设置值。需要注意的是,homeAddress 属性配置的是 simpleAddress 对象的引用。
被引用对象的配置定义无需早于引用其对象的定义。在本例中,employee1 对象可以出现在 simpleAddress 对象定义之前。
1.2.6 构造器方式依赖注入
清单 1.3 所示的 Employee 类提供了一个可以传递参数的构造器,我们还可以将 Address 对象通过构造器注入,如下所示:
<bean name="employee2" class="springintro.bean.Employee">
<constructor-arg name="firstName" value="Senior"/>
<constructor-arg name="lastName" value="Moore"/>
<constructor-arg name="homeAddress" ref="simpleAddress"/>
</bean>
<bean name="simpleAddress" class="springintro.bean.Address">
<constructor-arg name="line1" value="151 Corner Street"/>
<constructor-arg name="line2" value=""/>
<constructor-arg name="city" value="Albany"/>
<constructor-arg name="state" value="NY"/>
<constructor-arg name="zipCode" value="99999"/>
<constructor-arg name="country" value="US"/>
</bean>
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论