Spring知識一(bean配置)

IOC與DI概念

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

bean配置,ApplicationContext.xml中配置


<!-- 配置一個 bean 
    id爲在代碼中引用的名稱,唯一,且可以爲多個,利用逗號、分號、或空格分隔
    class執向全類名,spring就是根據全類名,通過反射生成一個實例對象,id爲這個實例對象的引用,所以我們必須在這個類中添加默認的構造方法,並且屬性要有setter方法
-->
<bean id="user" class="com.wf.springbean.User">
        <property name="name" value="tom"></property>
        <property name="sex" value="boy"></property>
    </bean>

加載配置文件,獲取bean

在 Spring IOC 容器讀取 Bean 配置創建 Bean 實例之前, 必須對它進行實例化. 只有在容器實例化後, 纔可以從 IOC 容器裏獲取 Bean 實例並使用。

Spring 兩種類型的 IOC 容器實現—重點

1.BeanFactory: IOC 容器的基本實現.
2.ApplicationContext: 提供了更多的高級特性. 是 BeanFactory 的子接口,可以根據不同的實現類,去加載配置文件。
注意:BeanFactory 是 Spring 框架的基礎設施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的開發者,幾乎所有的應用場合都直接使用 ApplicationContext 而非底層的 BeanFactory。

ApplicationContext 的主要實現類:
ClassPathXmlApplicationContext:從 類路徑下加載配置文件
FileSystemXmlApplicationContext: 從文件系統中加載配置文件
ConfigurableApplicationContext :擴展於 ApplicationContext,新增加兩個主要方法:refresh() 和 close(), 讓 ApplicationContext 具有啓動、刷新和關閉上下文的能力
ApplicationContext 在初始化上下文時就實例化所有單例的 Bean。【加載配置文件時】
WebApplicationContext 是專門爲 WEB 應用而準備的,它允許從相對於 WEB 根目錄的路徑中完成初始化工作

//1. 創建 Spring 的 IOC 容器 
//2. ClassPathXmlApplicationContext爲一個接口,ClassPathXmlApplicationContext是其中的一個實現類
//3. ClassPathXmlApplicationContext 是根據classpath路徑進行加載
ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("ApplicationContext.xml");

        // 1. 利用getBean方法獲取容器中bean實例
        User  user = (User) cxt.getBean("user");
        /*
         根據類型來獲取 bean 的實例: 要求在  IOC 容器中只有一個與之類型匹配的 bean, 若有多個則會拋出異常. 建議使用id進行匹配
        一般情況下, 該方法可用, 因爲一般情況下, 在一個 IOC 容器中一個類型對應的 bean 也只有一個. 
        HelloWorld helloWorld1 = ctx.getBean(HelloWorld.class);
        */

        // 1. 調用方法
        System.out.println(user.say());
        System.out.println(user);

依賴注入的方式—重點

屬性注入(最常用,記住)
構造器注入(一般用,瞭解)
工廠方法注入(很少使用,不推薦,可以忘記)

屬性注入:
屬性注入即通過 setter 方法注入Bean 的屬性值或依賴的對象,使用 元素, 使用 name 屬性指定 Bean 類的屬性名稱,value 屬性或 子節點指定屬性值。【在這裏,注入是根據setter方法來的而不是屬性名稱,但是一般我們都是直接生成setter方法,而不去更改這個名稱,所以就是說成name爲屬性名稱】

<bean id="user" class="com.wf.springbean.User">
        <property name="name" value="tom"></property>
        <property name="sex" value="boy"></property>
</bean>

構造方法注入:
通過構造方法注入Bean 的屬性值或依賴的對象,它保證了 Bean 實例在實例化後就可以使用。
構造器注入在 【constructor-arg】 元素裏聲明屬性,

<bean id="user01" class="com.wf.springbean.User">
        <!-- 要求: 在 Bean 中必須有對應的構造器.  -->
        <constructor-arg value="Mike" name="name"></constructor-arg>
        <constructor-arg value="girl" name="sex"></constructor-arg>
</bean>

    <!-- 若一個 bean 有多個構造器, 如何通過構造器來爲 bean 的屬性賦值 -->
    <!-- 可以根據 index(參數位置) 和 value 進行更加精確的定位. (瞭解) -->
    <bean id="car" class="com.wf.springbean.Car">
        <constructor-arg value="KUGA" index="1"></constructor-arg>
        <constructor-arg value="ChangAnFord" index="0"></constructor-arg>
        <constructor-arg value="250000" type="float"></constructor-arg>
    </bean>

    <bean id="car2" class="com.wf.springbean.Car">
        <constructor-arg value="ChangAnMazda"></constructor-arg>
        <!-- 若字面值中包含特殊字符, 則可以使用 DCDATA 來進行賦值. (瞭解) -->
        <constructor-arg>
            <value><![CDATA[<ATARZA>]]></value>
        </constructor-arg>
        <constructor-arg value="180" type="int"></constructor-arg>
    </bean>

引用其它 Bean—重點

組成應用程序的 Bean 經常需要相互協作以完成應用程序的功能. 要使 Bean 能夠相互訪問, 就必須在 Bean配置文件中指定對 Bean 的引用。
在 Bean 的配置文件中, 可以通過 【ref】 元素或 【ref】 屬性爲 Bean 的屬性或構造器參數指定對 Bean 的引用。
也可以在屬性或構造器裏包含 Bean 的聲明, 這樣的 Bean 稱爲內部 Bean。當 Bean 實例僅僅給一個特定的屬性使用時, 纔將其聲明爲內部 Bean. 內部 Bean 聲明直接包含在 【property】 或【constructor-arg】 元素裏, 不需要設置任何 id 或 name 屬性,內部 Bean 不能使用在任何其他地方。

<!-- 引用其他bean -->

<bean id="company" class="com.wf.springbean.Person">
<property name="name" value="longchuang"></property>
<property name="car" ref="car"></property>
<!--        <property name="car">
        <ref bean="car"/> 
        </property> 
-->
</bean>
<!-- 使用內部bean,不能被外部訪問-->
<bean id="company01" class="com.wf.springbean.Person">
    <property name="name" value="dazhong"></property>
    <property name="car">
        <bean class="com.wf.springbean.Car">
        <constructor-arg value="KUGA001" ></constructor-arg>
        <constructor-arg value="ChangAnFord001" ></constructor-arg>
        <constructor-arg value="250000" type="float"></constructor-arg>
        </bean>
    </property>
</bean>

注入參數詳解:null 值和級聯屬性—瞭解

可以使用專用的 【null】 元素標籤爲 Bean 的字符串或其它對象類型的屬性注入 null 值
和 Struts、Hiberante 等框架一樣,Spring 支持級聯屬性的配置。不建議使用級聯屬性這樣賦值,這樣的賦值,會覆蓋掉前面的bean中的此屬性的值

<!-- null測試及級聯屬性  利用構造注入時,必須保證構造函數-->

<bean id="person02" class="com.wf.springbean.Person">
    <constructor-arg name="name" value="jack"></constructor-arg>
    <!-- <constructor-arg name="car" ><null/></constructor-arg> -->
    <constructor-arg name="car" ref="car"></constructor-arg>
     <property name="car.maxSpeed" value="251"></property> 
<!-- 這種方式的賦值會將ref關聯的car的maxSpeed屬性進行更改。這樣的話,只要有涉及到car的都會更改-->
</bean>

集合屬性的配置—重點

在 Spring中可以通過一組內置的 xml 標籤(例如: 【list】, 【set】 或 【map】) 來配置集合屬性.
配置 java.util.List 類型的屬性, 需要指定 【list】 標籤, 在標籤裏包含一些元素. 這些標籤可以通過 【value】 指定簡單的常量值, 通過 【ref】 指定對其他 Bean 的引用. 通過【bean】 指定內置 Bean 定義. 通過 【null/】 指定空元素. 甚至可以內嵌其他集合.
數組的定義和 List 一樣, 都使用 【list】
配置 java.util.Set 需要使用 【set】 標籤, 定義元素的方法與 List 一樣.

Java.util.Map 通過 【map】 標籤定義, 【map】 標籤裏可以使用多個 【entry】 作爲子標籤. 每個條目包含一個鍵和一個值.
必須在 【key】 標籤裏定義鍵
因爲鍵和值的類型沒有限制, 所以可以自由地爲它們指定 【value】, 【ref】, 【bean】 或 【null】 元素.
可以將 Map 的鍵和值作爲 【entry】 的屬性定義: 簡單常量使用 key 和 value 來定義; Bean 引用通過 key-ref 和 value-ref 屬性定義

使用 【props】 定義 java.util.Properties, 該標籤使用多個 【prop】 作爲子標籤. 每個 【prop】 標籤必須定義 key 屬性,在整合hibernate時,會利用這個屬性

<!-- list 集合配置 -->      
<bean id="person" class="com.wf.springcollection.Person">
    <property name="name" value="rose"></property>
    <property name="cars">  
        <list>
            <ref bean="car1"/>
            <ref bean="car2"/>
            <ref bean="car3"/> 
            <bean class="com.wf.springcollection.Car">
                    <property name="company" value="tutu04"></property>
                    <property name="brand" value="HaFu04"></property>
                    <property name="maxSpeed" value="254"></property>
                    <property name="price" value="25400"></property>
        </bean> 
        </list>
    </property>
</bean>     

<!-- map集合配置 -->
<bean id="personmap" class="com.wf.springcollection.Person">
    <property name="name" value="jack"></property>
    <property name="mapscars">
        <map>
            <entry key="AA" value-ref="car1"></entry>
            <entry key="BB" value-ref="car2"></entry>
            <entry key="CC" value-ref="car3"></entry>
        </map>
    </property>
</bean>

<!-- prop配置,在整合hibernate使用 -->
<bean id="datasource" class="com.wf.springcollection.DataSource">
    <property name="properties">
    <props>
        <prop key="user">root</prop>
        <prop key="psaaword">1234</prop>
        <prop key="jbbcUrl">jdbc:mysql:///test</prop>
        <prop key="driverClass">com.mysql.jdbc.Driver</prop>
     </props>   

 </property>
</bean>


<!-- 將集合屬性進行單獨配置,這樣的話可以供多個bean使用,需要引入命名空間util -->
<util:list id="carslist">
        <ref bean="car1"/>
        <ref bean="car2"/>
</util:list>

<bean id="personlist" class="com.wf.springcollection.Person">
    <property name="name" value="jack"></property>
    <property name="cars" ref="carslist"></property>
</bean>


<!--p:命名空間的使用,可以簡化屬性配置  -->
<bean id="personp" class="com.wf.springcollection.Person"
p:name="Queen" p:cars-ref="carslist">

</bean>

自動裝配配置—瞭解

Spring IOC 容器可以自動裝配 Bean. 需要做的僅僅是在 【bean】 的 autowire 屬性裏指定自動裝配的模式。
1、byName(根據名稱自動裝配): 必須將目標 Bean 的名稱和屬性名設置的完全相同。
2、byType(根據類型自動裝配): 若 IOC 容器中有多個與目標 Bean 類型一致的 Bean. 在這種情況下, Spring 將無法判定哪個 Bean 最合適該屬性, 所以不能執行自動裝配。報錯。利用註解時,會用到bytype。
3、constructor(通過構造器自動裝配): 當 Bean 中存在多個構造器時, 此種自動裝配方式將會很複雜. 不推薦使用。

自動裝配的缺點:
在 Bean 配置文件裏設置 autowire 屬性進行自動裝配將會裝配 Bean 的所有屬性. 然而, 若只希望裝配個別屬性時, autowire 屬性就不夠靈活了.
autowire 屬性要麼根據類型自動裝配, 要麼根據名稱自動裝配, 不能兩者兼而有之.
一般情況下,在實際的項目中很少使用自動裝配功能,因爲和自動裝配功能所帶來的好處比起來,明確清晰的配置文檔更有說服力一些


<!--正常配置  -->
<bean id="user" class="com.wf.springauto.User">
    <property name="name" value="zhangsan"></property>
    <property name="car" ref="car"></property>
    <property name="address" ref="address"></property>

</bean>


<!-- 根據Name進行匹配。根據bean類的名字和當前setter風格的屬性名稱進行自動匹配 ,都是用在bean與bean之間的關聯中-->
<bean id="userautoname" class="com.wf.springauto.User" autowire="byName">
    <property name="name" value="zhangsan"></property>
        <!-- <property name="car" ref="car"></property>
        <property name="address" ref="address"></property> -->
</bean>

<!-- 根據type進行匹配。根據bean類的類型和bean的屬性類型進行自動裝配,都是用在bean與bean之間的關聯中-->
<bean id="userautotype" class="com.wf.springauto.User" autowire="byType">
    <property name="name" value="zhangsan"></property>
        <!-- <property name="car" ref="car"></property>
        <property name="address" ref="address"></property> -->
</bean>

現在的項目一般都是利用註解進行配置,因爲註解的方式可以大大縮減代碼量。但是在一些全局的屬性配置中,利用xml的配置還是比較方便。

源碼可以在我的資源中查看 或者 github地址:https://github.com/wangfa1994/SpringLearning/tree/spring001

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章