spring學習(二)Spring 中的 Bean 配置

IOC 和 DI

  • IOC(Inversion of Control):其思想是反轉資源獲取的方向. 傳統的資源查找方式要求組件向容器發起請求查找資源。
    作爲迴應, 容器適時的返回資源. 而應用了 IOC 之後, 則是容器主動地將資源推送給它所管理的組件,組件所要做的僅是選擇一種合適的方式來接受資源. 這種行爲也被稱爲查找的被動形式。
  • DI(Dependency Injection) — IOC 的另一種表述方式:即組件以一些預先定義好的方式(例如: setter方法)接受來自如容器的資源注入. 相對於 IOC 而言,這種表述更直接。

介紹IOC和DI這兩個概念是用來可以更好的去理解spring如何去創建對象的,在上一篇文章中使用spring獲取到了ApplicationContext對象後,可以直接用這個對象去實例化HelloWorld對象,而不需要去使用new來創建一個對象。那麼spring是如何去創建對象的,前面提到過ApplicationContext是Spring的IOC容器,在這個容器中spring爲我們去管理在配置文件中我們配置的哪些類的對象,需要使用時向spring中獲取這個對象,對象使用完畢後spring自動去回收這個對象。

在 Spring 的 IOC 容器裏配置 Bean

在 xml 文件中通過 bean 節點來配置 bean

<!--通過全類名的方式類配置bean-->
<bean id="helloworld" class="com.iflytek.test.bean.HelloWorld">
</bean>

id:Bean 的名稱。
- 在 IOC 容器中必須是唯一的 。
- 若 id 沒有指定,Spring 自動將權限定性類名作爲 Bean 的名字。
- id可以指定多個名字,名字之間可用逗號、分號、或空格分隔。

Spring 容器

在 Spring IOC 容器讀取 Bean 配置創建 Bean 實例之前, 必須對它進行實例化. 只有在容器實例化後, 纔可以從 IOC 容器裏獲取 Bean 實例並使用.。
Spring 提供了兩種類型的 IOC 容器實現.
- BeanFactory: IOC 容器的基本實現.。
- ApplicationContext: 提供了更多的高級特性. 是BeanFactory 的子接口.。
其中BeanFactory 是 Spring 框架的基礎設施,面向 Spring本身; ApplicationContext 面向使用 Spring 框架的開發者,幾乎所有的應用場合都直接使ApplicationContext 而非底層的 BeanFactory 無論使用何種方式, 配置文件時相同的。

ApplicationContext

1.ApplicationContext的繼承結構:
這裏寫圖片描述
2.ApplicationContext 的主要實現類:
- ClassPathXmlApplicationContext:從類路徑下加載配置文件。
- FileSystemXmlApplicationContext: 從文件系統中加載配置文件。
3.ConfigurableApplicationContext 擴展於 ApplicationContext,新增加兩個主要方法:refresh() 和 close(), 讓 ApplicationContext 具有啓動、刷新和關閉上下文的能力。
4.ApplicationContext 在初始化上下文時就實例化所有單例的 Bean。

從 IOC 容器中獲取 Bean

這裏寫圖片描述
調用 ApplicationContext 的 getBean(String) 方法,其中傳入的參數是在配置文件中配置bean時聲明的id。也可以調用getBean(Class) 方法,在使用該方法獲取bean的時候需要注意,如過在配置文件中聲明的同一個類有配置2個bean,那麼spring是無法知道你是要獲取哪一個bean的(當然一般情況下也不會出現這種配置兩次的情況)。

依賴注入的方式

Spring 支持 3 種依賴注入的方式
- 屬性注入
- 構造器注入
- 工廠方法注入(很少使用,不推薦)

屬性注入

-屬性注入即通過 setter 方法注入Bean 的屬性值或依賴的對象
-屬性注入使用 元素, 使用 name 屬性指定 Bean 的屬性名稱,value 屬性或 子節點指定屬性值
-屬性注入是實際應用中最常用的注入方式

<!--通過全類名的方式類配置bean-->
<bean id="helloworld" class="com.iflytek.test.bean.HelloWorld">
    <!-- 爲屬性賦值 -->
    <!-- 通過屬性注入: 通過 setter 方法注入屬性值 -->
    <property name="name" value="tom"></property>
</bean>

這種注入方式是之前的例子中寫過的

構造方法注入

通過構造方法注入Bean 的屬性值或依賴的對象,它保證了 Bean 實例在實例化後就可以使用。
構造器注入在 元素裏聲明屬性, 中沒有 name 屬性
將屬性注入註釋掉,使用構造器注入來看效果

    <!-- 通過構造器注入屬性值 -->
    <bean id="helloworld" class="com.iflytek.test.bean.HelloWorld">     
        <!--<property name="name" value="tom"></property>  -->
        <!-- 要求: 在 Bean 中必須有對應的構造器.  -->
        <constructor-arg value="lily"></constructor-arg>
    </bean>

對用的HelloWorld實體類

public class HelloWorld {

    private String name;
    //在無參的構造函數中打印一條消息
    public HelloWorld() {
        super();
        System.out.println("Constructed is used...");
    }


    public HelloWorld(String name) {
        super();
        this.name = name;
    }


    public String getName() {
        return name;
    }
//  //在set方法中打印信息
//  public void setName(String name) {
//      System.out.println("after name:"+name);
//      this.name = name;
//      System.out.println("before name:"+name);
//  }
//  
    public void hello(){
        System.out.println("hello:"+name);
    }
}

控制檯打印的結果:
這裏寫圖片描述
使用構造器注入屬性值的時候需要注意
寫一個新的實體類

public class Car {
    private int maxSpeed;
    private String name;
    private float price;
    public Car(int maxSpeed, String name, float price) {
        super();
        this.maxSpeed = maxSpeed;
        this.name = name;
        this.price = price;
    }
    @Override
    public String toString() {
        return "Car :maxSpeed=" + maxSpeed + ", name=" + name + ", price=" + price ;
    }   
}
    <!-- 若一個 bean 有多個構造器, 如何通過構造器來爲 bean 的屬性賦值 -->
    <!-- 可以根據 index 和 value 進行更加精確的定位. (瞭解) -->
    <bean id="car" class="com.iflytek.test.bean.Car">       
        <constructor-arg>
            <value>10</value>
        </constructor-arg>
        <constructor-arg value="寶馬"></constructor-arg>
        <constructor-arg value="15.5"></constructor-arg>
    </bean>
    <bean id="car1" class="com.iflytek.test.bean.Car">  
        <constructor-arg value="15.5" type="float"></constructor-arg>   
        <constructor-arg index="0">
            <value>10</value>
        </constructor-arg>
        <!-- 若字面值中包含特殊字符, 則可以使用 DCDATA 來進行賦值. (瞭解) -->
        <constructor-arg index="1">
            <value><![CDATA[寶馬@__@]]></value>
        </constructor-arg>      
    </bean>

控制檯打印的結果:
這裏寫圖片描述

###字面值

  • 字面值:可用字符串表示的值,可以通過 元素標籤或 value 屬性進行注入。
  • 基本數據類型及其封裝類、String等類型都可以採取字面值注入的方式
  • 若字面值中包含特殊字符,可以使用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章