設值注入

    設置注入是指IOC容器經過使用屬性的setter方法來注入被依賴的實列。仍是使用「人」和「斧子」的列子。java

定義一個Person接口,人都會使用「斧子」:spring

package com.custle.spring;

public interface Person {
	//人使用斧子
	public void useAxe();
}

定義一個「斧子」接口,該接口有一個「砍材」動做:app

package com.custle.spring;

public interface Axe {
	//斧子接口有個砍的方法
	public String chop();
}

具體的「中國人」實現Person接口:ide

package com.custle.spring;

public class Chinese implements Person {

	private Axe axe;
	
	//注入所須要的斧子
	public void setAxe(Axe axe) {
		this.axe = axe;
	}

	@Override
	public void useAxe() {
		System.out.println(axe.chop());
	}

}

具體的「石頭斧子」實現Axe接口:測試

package com.custle.spring;

public class StoneAxe implements Axe {

	@Override
	public String chop() {
		return "使用石斧砍材";
	}

}

這個時候程序並不知道Chinese使用的斧子是什麼類型的斧子,此時須要經過Spring來注入「斧子」至Chinese中,咱們經過setAxe()來設值注入。this

<?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.xs">
	
	<!-- 將stoneAxe注入chinese中的axe屬性至關於setAxe(stoneAxe)-->
    <bean id="chinese" class="com.custle.spring.Chinese">  
        <property name="axe" ref="stoneAxe"></property>  
    </bean>  
    
    <!-- 將StoneAxe交給Srping管理,否則Spring怎麼知道你要哪一種類型的斧子呢 -->
    <bean id="stoneAxe" class="com.custle.spring.StoneAxe"/>  
</beans>

    能夠看到Spring管理Bean的靈活性,Bean與Bean之間的依賴關係放在配置文件中,而不是經過代碼。經過配置文件的指定,Spring能精確的爲每一個Bean注入屬性。經過配置文件的指定,Spring能精確的爲每一個Bean注入屬性。所以<bean>裏面的class屬性不能爲接口,必須爲實現類。spa

    將 Chinese類進行修改,研究Spring具體是怎麼實現設值注入的過程: code

package com.custle.spring;

public class Chinese implements Person {

	private Axe axe;
	private String axe1;
	
	//經過property注入必須含有無參構造方法
	public Chinese() {
	}
	

	//注入StoneAxe石斧子類型,注意這裏爲Axe的實現類
	public void setAxe(StoneAxe axe) {
		this.axe = axe;
		System.out.println("axe="+axe.chop());
	}

	//注入String類型
	public void setAxe1(String axe1) {
		this.axe1 = axe1;
		System.out.println("axe1="+axe1);
	}

}

   測試方法:xml

public static void main(String[] args) throws Exception {
		//獲取Chinese的Class對象
		Class chinese = Class.forName("com.custle.spring.Chinese");
		Class stoneAxe = Class.forName("com.custle.spring.StoneAxe");
		//建立Chinese的默認實列
		Object bean = chinese.newInstance();
		Object stoneAxebean = stoneAxe.newInstance();
		//獲取axe屬性對應的setAxe1()方法,參數類型爲String
		Method method = chinese.getMethod("setAxe1", String.class);
		//獲取axe屬性對應的setAxe()方法,參數類型爲StoneAxe
		Method method1 = chinese.getMethod("setAxe", stoneAxe);
		//調用bean實列的setAxe1()方法
		method.invoke(bean, "hello world");
         //調用bean實列的setAxe()方法
		method1.invoke(bean, stoneAxebean);
	}

   控制檯輸出:對象

axe1=hello world
axe=使用石斧砍材

     若在Chinese類中將setAxe()方法修改成StoneAxe的抽象類Axe,會發現經過反射沒法將StoneAxe.Class注入。會報java.lang.NoSuchMethodException異常。

     Spring會經過反射自動接管每一個<bean>定義裏面的<property>,Spring會調用無參構造方法來構造該bean的實列,經過調用對應的setter方法爲程序注入屬性值,這也是咱們爲bean設置帶參構造器時,最好顯示聲明無參構造器的緣由。每一個bean的id惟一,程序經過bean的id訪問該bean,bean與bean之間依賴關係也經過id屬性關聯。

    經過Spring工廠去獲取Spring中的bean;

package com.custle.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class GetBeanFactory {
	private static ApplicationContext applicationContext;
	static{
		applicationContext = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
	}
	private static Chinese getInstance(){
       //經過配置文件中bean的ID獲取對應的bean
		Chinese chinese = (Chinese)applicationContext.getBean("chinese");
		chinese.useAxe();
		return chinese;
	}
}

    Chinese實列無須知道斧子的具體建立過程,當須要「跟換鋼斧子」時,只須要鋼斧子實現斧子接口,將該鋼斧子注入chinese中便可。

相關文章
相關標籤/搜索