Spring應用(一) IOC和DI總結

一、IOC和DI的概念描述

1.1概念

控制反轉(Inversion of Control,縮寫爲IoC),是面向對象編程中的一種設計原則,可以用來減低計算機代碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI)。


1.2技術描述

Class A中用到了Class B的對象b,一般情況下,需要在A的代碼中顯式的new一個B的對象。
採用依賴注入技術之後,A的代碼只需要定義一個私有的B對象,不需要直接new來獲得這個對象,而是通過相關的容器控制程序來將B對象在外部new出來並注入到A類裏的引用中。而具體獲取的方法、對象被獲取時的狀態由配置文件(如XML)來指定。


1.3實現方法

實現控制反轉主要有兩種方式:依賴注入和依賴查找。兩者的區別在於,前者是被動的接收對象,在類A的實例創建過程中即創建了依賴的B對象,通過類型或名稱來判斷將不同的對象注入到不同的屬性中,而後者是主動索取響應名稱的對象,獲得依賴對象的時間也可以在代碼中自由控制。


二、Spring IOC詳解

Spring的控制反轉:把對象的創建、初始化、銷燬等工作都交給Spring容器來做。由Spring容器控制對象的聲明週期。

2.1步驟

A.啓動spring容器

1、在類路徑下尋找配置文件來實例化容器
    ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});可以在整個類路徑中尋找xml文件
              * 通過這種方式加載。需要將spring的配置文件放到當前項目的classpath路徑下
              *  classpath路徑指的是當前項目的src目錄,該目錄是java源文件的存放位置。 
2、在文件系統路徑下尋找配置文件來實例化容器
ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{“d:\\beans.xml“});Spring的配置文件可以指定多個,可以通過String數組傳入。

注:經常用第一種方法啓動容器

B.從spring容器中提取對象


2.2 配置文件中的屬性

2.2.1 別名(alias)

<beans> 
    <bean name="person" class="cn.alias.spring.Person"/>
    <alias name="person" alias="p"/>
</beans>

通過這樣的配置,可以達到在一個地方命名,在多個地方使用不同的名字的效果。

2.2.2 bean對象的scope

singleton(默認值)

在每個Spring IoC容器中一個bean定義只有一個對象實例(共享)。
默認情況下會在容器啓動時初始化bean,但我們可以指定Bean節點的lazy-init=“true”來延遲初始化bean,這時候,只有第一次獲取bean會才初始化bean。如:

 <bean id="xxx" class="cn.OrderServiceBean" lazy-init="true"/>

如果想對所有bean都應用延遲初始化,可以在根節點beans設置default-lazy-init=“true“,如下:

<beans default-lazy-init="true“ ...> 

這裏寫圖片描述

prototype

允許bean可以被多次實例化(使用一次就創建一個實例) . Spring不能對一個prototype bean的整個生命週期負責.這就意味着清楚prototype作用域的對象並釋放任何prototype bean所持有的昂貴資源都是客戶端的責任。

2.2.3 Lazy-init

Spring默認在啓動時將所有singleton bean提前進行實例化。提前實例化意味着作爲初始化的一部分,ApplicationContext會自動創建並配置所有的singleton bean.通常情況下這是件好事。因爲這樣在配置中有任何錯誤能立即發現。
Lazy-init=”true or false”
Lazy-init 爲false,spring容器將在啓動的時候報錯(比較好的一種方式)
Lazy-init 爲true,spring容器將在調用該類的時候出錯。

2.2.4init、destroy

Spring初始化bean或銷燬bean時,有時需要作一些處理工作,因此spring可以在創建和拆卸bean的時候調用bean的兩個生命週期方法。

<bean id=“foo” class=“...Foo” init-method=“setupdestory-method=“teardown”/>

當foo被載入到Spring容器中時調用init-method方法。當foo從容器中刪除時調用destory-method(scope = singleton有效)


2.3 創建對象的三種方式

2.3.1 無參構造函數

<bean id=“personService" class="cn.bean.impl.PersonServiceImpl"/>

* 要求PersonServiceImpl有無參構造方法
* spring容器在默認的情況下使用默認的構造函數創建對象

2.3.2 靜態工廠方法

<bean id="personService" class="com.factory.PersonServiceFactory" factory-method="createPersonService" />


public class PersonServiceFactory {
      public  static PersonService createPersonService(){
                return new PersonServiceImpl();
      }
}
/**
 * 在spring容器 內部,調用了PersonServiceFactory中的createPersonService方法
 * 而該方法的內容就是創建對象的過程,是由程序員來完成
 */

2.3.3 實例工廠

<bean id="helloWorldFactory" class="com.spring.ioc.createobject.method.HelloWorldFactory2"></bean>

    <!-- 
        factory-bean指向了實力工廠的bean
        factory-method實例工廠對象的方法
     -->
<bean id="helloWorld" factory-bean="helloWorldFactory" factory-method="getInstance"></bean>
/**
 * 實例工廠
 *   1、spring容器創建一個實例工廠bean
 *   2、該bean調用了工廠方法getInstance產生對象
 */

三、Spring DI詳解

依賴注入(Dependence Injection)是把Spring創建的對象注入到Java類中

有三種注入方式,分別爲setter注入,構造器注入,註解注入,其中前兩種方法都是在xml文件中配置

3.1 setter注入

    <bean id="person" class="com.spring.di.xml.setter.Person">
        <!-- 
            property描述的就是bean中的屬性
              name屬性就是描述屬性的名稱
              value就是值   如果是基本屬性(String),就用value賦值
              ref  如果是引用類型,用ref賦值
         -->
        <property name="pid" value="1"></property>
        <property name="name" value="王二麻子"></property>
        <property name="student" ref="student"></property>
        <property name="lists">
            <list>
                <value>list1</value>
                <value>list2</value>
                <!-- 
                    list中存放一個student對象
                 -->
                <ref bean="student"/>
            </list>
        </property>
        <property name="objects">
            <list>
                <value>obj1</value>
                <ref bean="student"/>
            </list>
        </property>
        <property name="sets">
            <set>
                <value>set1</value>
                <ref bean="student"/>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="m1">
                    <value>m1</value>
                </entry>
                <entry key="m2">
                    <ref bean="student"/>
                </entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="p1">p1</prop>
                <prop key="p2">p2</prop>
            </props>
        </property>
    </bean>

3.2 構造器注入

    <bean id="person" class="com.spring.di.xml.constructor.Person">
        <!-- 
            constructor-arg  代表某一個構造器的參數
              index 構造器參數的下標
              value
              ref
              type  類型
         -->
        <constructor-arg index="0" value="1" type="java.lang.String"></constructor-arg>
        <constructor-arg index="1" ref="student"></constructor-arg>
    </bean>

Person類中:

    public Person(String name,Student student){
        this.name  = name;
        this.student = student;
    }

3.3 註解注入

3.3.1 步驟

步驟:
A.在配置文件中,引入context命名空間

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring- beans-2.5.xsd
                      http://www.springframework.org/schema/context
                   http://www.springframework.org/schema/context/spring-context-2.5.xsd">

B.在配置文件中加入context:annotation-config標籤

<context:annotation-config/> 

這個配置隱式註冊了多個對註釋進行解析處理的處理器
AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor
注: @Resource註解在spring安裝目錄的lib\j2ee\common-annotations.jar

3.3.2 @Resource

1、@Resource註解和@Autowired一樣,也可以標註在字段或屬性的setter方法上.
2、@Resource註解默認按名稱裝配。
名稱可以通過@Resource的name屬性指定,如果沒有指定name屬性,
•當註解標註在字段上,即默認取字段的名稱作爲bean名稱尋找依賴對象
•當註解標註在屬性的setter方法上,即默認取屬性名作爲bean名稱尋找依賴對象。


/**
 * 1、啓動spring容器
 * 2、把spring配置文件中的bean實例化(person,student)
 * 3、當spring容器解析配置文件
 *     <context:annotation-config></context:annotation-config>
 *    spring容器會在納入spring管理的bean的範圍內查找哪些類的屬性上是否加有@Resource註解
 * 4、如果在屬性上找到@Resource註解
 *      如果@Resource的註解的name屬性的值爲""
 *           則把@Resource所在的屬性的名稱和spring容器中的id作匹配
 *                  如果匹配成功,則賦值
 *                  如果匹配不成功,則會按照類型進行匹配
 *                      如果匹配成功,則賦值,匹配不成功,報錯
 *      如果@Resource的註解的name屬性的值不爲""
 *           則解析@Resource註解name屬性的值,把值和spring容器中的ID進行匹配
 *               如果匹配成功,則賦值
 *               如果匹配不成功,則報錯
 *               
 * 說明:
 *     註解代碼越來越簡單,效率越來越低
 *     註解只能應用於引用類型
 */

@Autowired和@Qualifier結合起來用與@Resource效果一樣

3.3.3 @Autowired

這兩個註解的區別是:@Autowired 默認按類型裝配,@Resource默認按名稱裝配,當找不到與名稱匹配的bean纔會按類型裝配。

3.3.4 @Qualifier

3.3.4 @PostConstruct

指定Bean的初始化方法

3.3.4 @PreDestroy

指定Bean的銷燬方法

3.4 Spring中的繼承

Spring-Context之九:在bean定義中使用繼承
作者:黃博文@無敵北瓜

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