閱讀754 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《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

  上一篇:go  《Spring MVC學習指南(第2版)》——1.3 小結
  下一篇:go  網絡是時間同步服務器模塊化分布式體係