亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

首頁 慕課教程 Spring 入門教程 Spring 入門教程 Spring IoC (控制反轉)之 xml 配置

Spring IoC (控制反轉)之 xml 配置

1. 前言

本小節目的在于帶領大家熟練 xml 文件配置, 應用 xml 文件配置 IoC。

在第二節中我們通過一個入門工程簡單地體驗了一把 Spring 的使用。在第三節中梳理了一下 Spring 的工作流程。

大家有了一個初步認知,Spring 框架的工作脫離不了核心配置文件 applicationContext.xml。

在配置文件中我們目前只用到了一個 bean 標簽,它的作用是用于描述 Java 的類,讓框架啟動加載配置文件實例化的。

疑問導出

那么我們知道描述一個類有幾個要素,類名、屬性、構造函數 set 和 get 方法對吧?而 bean 標簽如何描述一個詳細的類呢?

帶著疑問… 開始本節內容。

2.bean 標簽中的屬性介紹

核心配置文件回顧

<bean id="user" class="com.wyan.entity.User" ></bean>  


在上面的代碼中可以看到,在 bean 標簽中有兩個屬性,一個是 id 一個是 class。那么在 bean 標簽中都有哪些屬性呢?

屬性列表

學號 姓名
id 定義的唯一標識
name 同 id 的意義一致
class
factory-bean 工廠對象
factory-method 工廠方法
init-method 初始化執行的方法
destroy-method 銷毀執行的方法
scope 對象的作用域
lazy-init 懶加載
autowire 依賴注入
depends-on 依賴于某個實例

疑問導出

上述屬性是配置 bean 標簽中可以選擇的屬性,當然一般來講,我們無需配置所有,可以根據自己的需求配置需要的屬性信息,那么如何選擇這些屬性呢?

2.1 屬性詳細解釋

2.1.1 id 和 name 標簽的使用

我們目前已經知道所有被實例化后的對象都存在于 Spirng 的容器中,那么從容器中獲取這些對象需要一個屬性 id 對吧?那么 name 和 id 有什么關系呢?

查看官方文檔得知 Spring 的容器會給初始化的每個 bean 都定義一個或多個標識符。這些標識符在容器內必須是唯一的。一個 bean 通常只有一個標識符。而 name 和 id 都可以起到標識符的作用。

所以在 XML 配置文件,我們一般使用 id 或者 name 屬性,定義 bean 的唯一標識,
這樣我們才能通過定義好的唯一標識,從 Spring 的容器中獲取他們。
代碼實例:

xml 的配置文件如下:

<?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 id="user" name="user2" class="com.wyan.entity.User" ></bean>

</beans>

測試代碼如下:

	public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        System.out.println(context.getBean("user"));
        System.out.println(context.getBean("user2"));
    }

結果如圖所示:

圖片描述
結論證明

我們通過 bean 標簽中的 id 屬性 user, 或者使用 bean 標簽中的 name 屬性 user2, 都可以得到 Spring 容器中的 user 對象的示例,而且打印的地址是同一個。我們之前說過一句,默認在容器中的實例都是單例的,在這里也得到了證明。

2.1.2 class 屬性

bean 標簽的定義實質上是創建一個或多個對象的方法。當 xml 文件被解析加載的時候,使用該 bean 定義封裝的配置數據來創建(或獲取)實際對象,而創建獲取的對象是誰呢?就是通過 class 屬性中定義的類的全路徑來指定 。

一般來講 class 中的類實例化有兩種方式

? 一種是反射 ,相當于我們使用的 new 關鍵字。這種也是我們常用的方式。當然不要忘記提供無參數的構造方法(類中默認有無參構造,但是如果自定義了有參構造,默認的無參不會提供)

? 一種是工廠模式 ,需要借助于 factory-bean 和 factory-method 兩個屬性,這種方式不常用,我們可以了解下。

2.1.3 factorybean 和 factorymethod 屬性

這兩個屬性主要用于工廠模式實例化 bean 的時候使用,不是很常見。工廠模式有兩種,這里分別做個實例,幫助大家理解。

靜態工廠模式實例:

<!--applicationContext的配置bean節點-->
<bean id="user" class="com.wyan.entity.User" factory-method="createUserInstance"/>

創建 bean 示例的 Java 工廠類:

public class User {
    
    private static User user = new User();
    
    private User() {}

    public static User createInstance() {
        return user;
    }
}

解釋:在定義使用靜態工廠方法創建的 bean 時,class 屬性指定的是被創建的類,包含靜態的方法,并使用 factory-method 屬性來指定工廠方法本身名稱。

普通工廠模式

<!--spring實例化工廠對象 用于創建java實例 -->
<bean id="beanFactory" class="com.wyan.factory.BeanFactory"></bean>
<!-- 被工廠創建的對象實例 -->
<bean id="user1" factory-bean="beanFactory" factory-method="createUser1"/>

工廠類代碼:

public class BeanFactory {

    private static User1 user1 = new User1();

    private static User2 user2 = new User2();

    public User1 createUser1() {
        return user1;
    }

    public User2 createUser2() {
        return user2;
    }
}

解釋:先實例化先創建各個對象示例的工廠對象到容器中,自身的 bean 標簽將 class 屬性保留為空,并在 factory-bean 屬性中指定當前容器中的工廠 Bean 名稱,再使用 factory-method 屬性設置創建示例的方法名稱。

2.1.4 init-method 和 destroy-method 屬性的使用

這兩個屬性比較好理解 init-method 就是 bean 被初始化后執行的方法,destory-method 就是 bean 被銷毀執行的代碼。

我們來個測試類

public class User {

    public User(){
        System.out.println("我被spring實例化了");
    }

    public void initMethod(){
        System.out.println("user類實例化時候執行的代碼");
    }
    public void destoryMethod(){
        System.out.println("user類實例被銷毀時候執行的代碼");
    }
}

配置文件

 <bean id="user" name="user2" class="com.wyan.entity.User" init-method="initMethod" destroy-method="destoryMethod" ></bean>**

測試代碼:

	public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
       
    }

加載 Spring 的配置文件控制臺打印如下:
圖片描述

有個小疑問:銷毀語句沒打印呢?那是因為并沒有調用容器的銷毀方法。

改造測試代碼如下:

	public static void main(String[] args) {
        AbstractApplicationContext context =
                new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        context.close();
    }

解釋:ApplicationContext 沒有 close 方法使用它的子類

運行結果:

圖片描述

2.1.5 其余屬性作用

scope :指定示例的作用范圍,后續章節詳細講解;

lazy-init :表示是否為懶加載;

autowire :指定屬性注入方式,后續章節詳解;

depends-on: 表示是否有依賴的 bean 對象,后續依賴注入章節詳細解釋。

2.2 構造函數的使用

剛剛我們詳細解釋了 bean 標簽內部的屬性,經過幾個小實例以后不禁也有個問題:

如果我們定義的類中有一些初始化的參數,并且定義好了有參數的構造,通過 xml 配置文件如何體現呢?

實現起來非常簡單,跟我來進行一個小實例:

改造 User 類

這是一個普通的 Java 類對象,包含兩個屬性及其 get 和 set 方法,并且提供了空參構造和有參構造,為了測試方便再覆寫一個 toString 方法。

public class User {

    private Integer id;
    private String name;
    
    public User() {
    }
    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

xml 配置文件方式

    <bean id="user"  class="com.wyan.entity.User"  >
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="zs"></constructor-arg>
    </bean>

測試結果

圖片描述
其實對于有參構造實例化對象而言,使用一個標簽 constructor-arg 即可,表示構造的參數,如果有多個,可以繼續添加,這里不多做演示。

疑問導出

可能有同學會想,那么如果以后我們的屬性需要動態更改呢?或者我們的屬性不是基本類型而是另外的對象呢? 后續在第三章依賴注入多種屬性的小節給大家講解 。

3. 小結

本章節帶著大家詳細解釋了 bean 標簽的使用,那么通過本章節我們收獲了哪些呢?

  1. 容器內部命名唯一標識可以通過 id 也可以通過 name;

  2. 實例化對象有兩種方式 反射模式和工廠模式;

  3. 如果是反射模式,那么必須配置 class 屬性,因為需要用 class 屬性中類的全路徑來實例化 bean 對象;

  4. 如果需要在類實例化初始化參數,可以使用 init 方法也可以使用有參構造。

持之以恒的學習是成功的最快捷徑… 切記眼高手低。