1. 程式人生 > >spring(一)控制反轉和依賴注入

spring(一)控制反轉和依賴注入

       控制反轉降低了類和類之間的耦合度,利於修改和擴充套件,提供了完整的IOC實現,讓我們專注於業務類和Dao類的設計,體現的是面向介面程式設計的思想,核心是BeanFactory。

需要引入的架包:

commons-logging: spring執行依賴這個元件;

此外還要spring-beans;spring-context;spring-core;spring-expression元件。

本例定個三個介面;Print(印表機),Paper(紙張),Ink(墨盒)

例如:印表機用彩色墨盒在A4紙上列印。

一、初始簡單控制反轉

1. 建立紙張介面和實現類

public interface Paper {
	public String getSize();
}
public class A4Paper implements Paper{
	private String size="A4";
	
	public String getSize() {
		return size;
	}

	public void setSize(String size) {
		this.size = size;
	}
	
}

2. 建立配置檔案applicationContext.xml

新增resource路徑,用來放配置檔案;

applicationContext.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"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd">
		
<!-- 1.IoC控制反轉
		建立物件,通過bean元素宣告需要Spring例項,即物件,id為例項指定名稱,class指明瞭物件的型別 -->
	<bean id="A4" class="com.A4Paper"></bean>
</beans>	

3. 測試

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Paper paper = (Paper)ac.getBean("A4");
		System.out.println(paper.getSize());
	}
}

輸出: A4。

不用再像以前一樣通過new A4Paper()來建立物件,都交給了容器實現,實現瞭解耦。

二、注入值

以上的A4Paper的值是實現了中設定的,現在通過spring 的DI(依賴注入)來設定值。

1. 增加Ink介面和實現類

public interface Ink {
	public String getColor();
}
public class ColorsInk implements Ink{
	private String color;
	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
}

不設定具體的值,再配置檔案中注入。

2.. 增加print類

public class Print {
	private Paper paper;
	private Ink ink;
	
	public Paper getPaper() {
		return paper;
	}

	public void setPaper(Paper paper) {
		this.paper = paper;
	}

	public Ink getInk() {
		return ink;
	}

	public void setInk(Ink ink) {
		this.ink = ink;
	}
	
	/**
	 * 
	 */
	public Print() {
		super();
	}

	/**
	 * @param paper
	 * @param ink
	 */
	public Print(Paper paper, Ink ink) {
		super();
		this.paper = paper;
		this.ink = ink;
	}

	public void print(){
		System.out.println("使用"+ink.getColor()+"墨盒,在"+paper.getSize()+"紙上列印");
	}
}

兩個介面引數,不關注具體的實現,只關注介面的使用。

3. applicationContext.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"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd">
		
<!-- 1.IoC控制反轉
		建立物件,通過bean元素宣告需要Spring例項,即物件,id為例項指定名稱,class指明瞭物件的型別 -->
	<bean id="A4" class="com.A4Paper"></bean>
	<bean id="color" class="com.ColorsInk">
		<property name="color" value="紅色"></property>
	</bean>
	<bean id="print" class="com.Print">
<!-- 2.DI依賴注入,面向介面程式設計  setter注入,可以把ref作為標籤寫在外邊,必須有無參構造,在物件建立後賦值
		把一個例項注入到另一個例項的屬性,用ref注入,name指定set後的屬性,在本容器中完成的-->
		<property name="ink" ref="color"/>	
		<property name="paper">
			<ref bean="A4"></ref>
		</property>
	</bean>
</beans>

4. 測試

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Print print = (Print)ac.getBean("print");
		print.print();
	}
}

結果: 使用紅色墨盒,在A4紙上列印。

三、幾種依賴注入方式        


<!--1. setter注入,可以把ref作為標籤寫在外邊,必須有無參構造,在物件建立後賦值
        把一個例項注入到另一個例項的屬性,用ref注入,name指定set後的屬性,在本容器中完成的-->
<bean id="print" class="cn.bdqn.springIoC.Print">
        <property name="ink" ref="gray"/>    
        <property name="paper">
            <ref bean="A4"></ref>
        </property>
    </bean>
 <!-- 構造注入 ,必須有有參的構造方法,-->
    <bean id="print1"  class="cn.bdqn.springIoC.Print">
        <constructor-arg index="0">
            <ref bean="A5"></ref>
        </constructor-arg>
        <constructor-arg index="1">
            <!-- 引用的類有id -->
            <ref bean="color"></ref>
            <!-- 沒有建立id,用bean標籤直接引用類 -->
    <!--     <bean class="cn.bdqn.springIoC.ColorsInk"></bean>  -->
        </constructor-arg>
    </bean>
    <bean id="greet" class="cn.bdqn.springIoC.Greeting">
<!-- 3.setter注入值,給例項的屬性賦值,必須有set方法,value是具體的值,name指定set後的屬性 -->
        <property name="person">
            <value>嘎子</value>
        </property>
        <property name="words">
            <value>三天不打小鬼子,手都癢癢。--setter注入值,</value>
        </property>
    </bean>
<!-- 4.constructor-arg構造注入值,構造器 ,必須有構造方法,可以把value當作屬性寫裡邊,也可以放在外邊當作標籤-->    
    <bean id="rod" class="cn.bdqn.springIoC.Greeting">
        <constructor-arg index="0">
            <value>Rod</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>世界上有兩種人,認識二進位制的和不認識二進位制的。--使用constructor-arg構造注入值</value>
        </constructor-arg>
<!--         <property name="person">
            <value>Rod</value>
        </property>
        <property name="words">
            <value>世界上有兩種人,認識二進位制的和不認識二進位制的。</value>
        </property>
 -->        
    </bean>
<!-- 5.p名稱空間實現屬性注入 ,先加p的宣告,在bean內部設定 p:屬性名=”屬性值“,用到的比較少,解析易出錯-->    
    <bean id="Tom" class="cn.bdqn.springIoC.Greeting" p:person="Tom" p:words="張嘎是個黑胖子--p名稱空間內部設定">
    <!--     <property name="person" value="Tom"/>
        <property name="words" value="張嘎是個黑胖子"/>     -->
    </bean>
<!-- 6.注入不同型別的資料,有特殊字元的 -->    
    <bean id="朱文俊" class="cn.bdqn.springIoC.Greeting">
        <property name="person" value="朱文俊">
        </property>
        <property name="words">
        <!--      <value>a>b</value>-->
            <value>a&lt;b 採用預定義實體</value>
        </property>
    </bean>
<!-- 7.集合注入 -->    
    <bean id="list" class="cn.bdqn.springIoC.Student1">
        <property name="person" value="老師">
        </property>
        <property name="words" value="這是集合的設定值"></property>
    <!-- 集合和陣列,用list -->    
        <property name="list">
            <list>
                <value>List1</value>
                <value>List2</value>
                <value>List3</value>
            </list>
        </property>
    <!-- set集合,用set -->    
        <property name="set">
            <set>
                <value>List1:兩個一樣的list2,只會顯示一個</value>
                <value>List2</value>
                <value>List2</value>
            </set>
        </property>
    <!-- map集合用下邊的標籤 -->    
        <property name="map">
            <map>
                <entry>
                    <!-- key的value必須放在外邊 -->
                    <key ><value>鍵一</value></key>
                    <value>第一對</value>
                </entry>
                <entry>
                    <key ><value>鍵二</value></key>
                    <value>第二對</value>
                </entry>
            </map>
        </property>
    <!-- Properties類集合,用props標籤 -->    
        <property name="property">
            <!-- 輸出null -->
    <!--     <null/>  -->    
            <!-- 空的“”,{} -->
            <value></value>
    <!--         <props>
                <prop key="prop1">鍵所對應的值1</prop>
                <prop key="prop2">鍵所對應的值2</prop>
                <prop key="prop3">鍵所對應的值3</prop>
            </props>
             -->
        </property>
    </bean>
    
    
</beans>