《Spring MVC學習指南(第2版)》——1.2 Spring控製反轉容器的使用
本節書摘來自異步社區《Spring MVC學習指南(第2版)》一書中的第1章,第1.2節,作者:【美】Paul Deck著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看
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="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
< bean name="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
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
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" >
<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" >
<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" >
<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" >
<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" >
<constructor-arg name="firstName" value="Senior"/>
<constructor-arg name="lastName" value="Moore"/>
<constructor-arg name="homeAddress" ref="simpleAddress"/>
</bean>
<bean name="simpleAddress" >
<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>
最後更新:2017-05-27 12:01:28