1. 程式人生 > >Spring:設值注入用法

Spring:設值注入用法

首先明確Java中什麼是依賴關係:

  類A依賴類B的意思是,如果A的物件要完成某一操作,必須使用B的物件的某些操作來幫忙,才能完成。簡言之,B作為A的某個方法的方法引數存在。如下:

class A{
       public void f(B b){
 
}
}
class B{
 
}
  


Spring的作用就是管理JavaEE中的各個元件,並把所有的Java物件都稱之為Bean,因此完全可以把任何的Java類都部署在Spring中,但是Java類中必須有相應的構造器。 

  設值注入通過<property/>元素驅動Spring執行setter方法,為引數傳入引數值,而Java類的成員變數又可以是各種資料型別,除了基本的資料型別外,還可以是其他Java例項,也可以是Spring容器中其他Bean例項,甚至是Java集合,陣列等,因此Spring允許如下元素為setter方法、構造器引數指定引數值。

1:value  用於注入基本資料型別

2:ref   當注入的成員變數屬於Sping容器中的其他Bean例項則應使用ref元素。

3:bean  稱之為注入巢狀Bean,當某個Bean所依賴的Bean不想被容器訪問,則可以使用巢狀Bean,其本質與ref一樣

4:list、set、map、props 當注入的成員變數屬於集合時則使用這些元素。

  Spring可以為任何Java物件注入任何型別的屬性,只要該Java物件為該屬性提供了相應的setter方法,Spring就是通過該方法,完成的相應賦值和注入。

一:當注入普通屬性時—————value元素的使用

1:我們定義一個Bean例項的實現類 Test.java

package com.mao.test;

public class Test {
	private String userName;
	//為Spring容器注入普通屬性提供setter方法
	public void setUserName(String userName) {
		this.userName = userName;
	}

	public void input(){
		System.out.println("正在呼叫setUserName()方法,傳入的引數為:"userName);
	}
}


該類中聲明瞭一個普通屬性 userName,並提供了set方法,Spring容器也正是通過該方法完成的屬性注入。

2:我們的配置檔案beans.xml

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<!-- 建立一個id為test的Bean例項 -->
	<bean id="test" class="com.mao.test.Test">
	  <!-- 通過setName方法為引數賦值  引數值為VipMao -->
	  <property name="userName" value="VipMao"></property>
	</bean>
</beans>

說一下配置檔案,我們定義了一個id為test的Bean例項,他的實現類是com.mao.test包下的Test.java(也就是上面那個程式),然後<bean>內定義了個<property>標籤,name屬性的值表示呼叫哪個屬性的set方法進行注入賦值,value屬性得值表示傳入的引數是什麼。上面的配置檔案就是:有一個test的Bean例項,然後Spring容器通過setUserName方法,將VipMao引數注入給userName屬性。咱們僅僅需要提供一個setter方法,然後"坐等"Spring通過該setter方法完成賦值並注入給userName屬性。

3:我們的測試類 TestManager.java

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

public class TestManager {
	public static void main(String[]args){
		ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
		//獲取Bean例項
		Test t=(Test) ctx.getBean("test");
		//執行input方法
		t.input();
	}
}

4:執行結果

正在呼叫setUserName()方法,傳入的引數為:VipMao

  可以看出,在主程式測試類中我們並沒有通過程式碼設定name屬性的值,而是<property/>元素驅動Spring容器通過相應的set方法,將value元素的值注入給屬性,但是前提是:

(1):在Bean 例項中提供了相應的setter方法(Spring容器通過該方法注入)

(2):該屬性為普通屬性(上面的name屬性為String型)

二:注入的屬性為Spring中的另一個Bean屬性----ref元素的使用

如果我們在一個Bean例項中的一個方法中使用了另一個Bean例項,也就是上面說的依賴關係,或者說需要為Bean設定的屬性值是容器中的另一個Bean的例項,則應該使用ref元素。如下例子:

1:Bean例項 Person.java

package com.mao.test;

public class Person {
	private Chinese chinese;

	public Person() {
		System.out.println("----------Spring容器通過呼叫無參建構函式建立Bean例項----------");
	}

	public void setChinese(Chinese chinese) {
		this.chinese = chinese;
	}
	public void useChinese(){
		System.out.println(chinese.say());
	}
}
上面聲明瞭一個Chinese屬性,並提供了setter方法,在Person類useChinese()方法中用到了chinese例項,接下來我們看一下Spring容器怎麼通過ref元素將Chinese例項注入給chinese

2:我們的配置檔案beans.xml

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
        <!-- 定義chinesePerson Bean例項,實現類Chinese類 -->
	<bean id="chinesePerson" class="com.mao.test.Chinese"></bean>
	<!-- 建立一個person Bean 實現類Person類-->
	<bean id="person" class="com.mao.test.Person">
	  <!-- 驅動呼叫person的setChinese()方法,將容器中的chinesePerson Bean例項作為傳入引數 -->
	  <property name="chinese" ref="chinesePerson"></property>
	</bean>
</beans>
配置檔案中先定義了一個chinesePerson Bean例項,實現類是Chinese類,然後定義了一個person的Bean例項,<property>內的name和ref元素值就是:通過Person類的setChinese方法將容器中的chinesePerson Bean例項作為引數注入給chinese,這就相當於執行了 Chinese chinese=new Chinese(); 只不過這個過程是Spring通過set方法實現的。

3:被引用的chinese Bean例項 Chinese.java

package com.mao.test;

public class Chinese {
	public String say(){
		return"我是中國人";
	}
}<span style="font-size:14px;">
</span>

4:測試程式 PersonManager.java

public class PersonManager {
	public static void main(String[]args){
		ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
		//獲取person Bean例項
		Person p=(Person) ctx.getBean("person", Person.class);
		p.useChinese();
}
}


5:輸出結果:


可以看出,我們並沒有在主程式中通過new的方式建立Chinese物件,這一切都是Spring容器通過ref引用chinesePerson的Bean例項,將該例項作為引數通過setter方法完成賦值和注入,通過輸出結果我們也可以發現Spring容器是通過無引數構造器來建立Bean例項的

三:注入巢狀Bean

   當某個Bean所依賴的Bean不想被Spring容器直接訪問時,例如上一個例子person的Bean例項需要依賴chinese的Bean例項,則可以使用巢狀Bean,將chinese的Bean例項巢狀進person的Bean例項,因為巢狀Bean例項的本質是和ref引用容器是一樣的,因此我們完成上一個例子,僅需稍微修改一下配置檔案beans.xml

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<!-- 建立一個person Bean 實現類Person類-->
	<bean id="person" class="com.mao.test.Person">
	  <!-- 驅動呼叫person的setChinese()方法,將容器中的chinesePerson Bean例項作為傳入引數 -->
	  <property name="chinese">
	  <!-- 定義chinesePerson Bean例項,實現類Chinese類 -->
	  <bean class="com.mao.test.Chinese"></bean>
	  </property>
	</bean>
</beans>

如上,將chinese的Bean例項巢狀到person Bean的<property>子元素,那麼該chinese Bean就僅僅作為setter注入的引數,由於不需要容易訪問該Bean,因此也就不需要指定id屬性。

其他程式碼不用改,執行結果依舊:


四:注入集合值

  當我們需要注入集合值時,我們則可以使用集合元素<list/><set/><map/><props>分別為List、Set、Map、和Properties的集合設定屬性值,如下:

1:Chinese.java

package com.mao.collection;

import java.util.*;

public class Chinese implements Person{

	// 下面是系列集合型別的成員變數
		private List<String> schools;
		private Map scores;
		private Map<String , Axe> phaseAxes;
		private Properties health;
		private Set axes;
		private String[] books;

		public Chinese()
		{
			System.out.println("Spring例項化主調bean:Chinese例項...");
		}

		// schools的setter方法
		public void setSchools(List schools)
		{
			this.schools = schools;
		}
		// scores的setter方法
		public void setScores(Map scores)
		{
			this.scores = scores;
		}
		// phaseAxes的setter方法
		public void setPhaseAxes(Map<String , Axe> phaseAxes)
		{
			this.phaseAxes = phaseAxes;
		}
		// health的setter方法
		public void setHealth(Properties health)
		{
			this.health = health;
		}
		// axes的setter方法
		public void setAxes(Set axes)
		{
			this.axes = axes;
		}
		// books的setter方法
		public void setBooks(String[] books)
		{
			this.books = books;
		}

		// 訪問上面全部的集合型別的成員變數
		public void test()
		{
			System.out.println("----開始輸出List集合--------");
			Iterator it=schools.iterator();
			while(it.hasNext()){
				System.out.println(it.next());
			}
			System.out.println("--------開始輸出Map集合---------- ");
			System.out.println(scores);
			System.out.println("---------開始遍歷<String,Axe集合>----------");
			System.out.println(phaseAxes);
			System.out.println("---------開始遍歷Properties----------");
			System.out.println(health);
			System.out.println("---------開始遍歷Set集合----------");
			Iterator itSet=axes.iterator();
			while(itSet.hasNext()){
				System.out.println(itSet.next());
			}
			System.out.println("-----開始遍歷Array陣列集合-------------");
			System.out.println(java.util.Arrays.toString(books));
			for(String array:books){
				System.out.println(array);
			}
			
		}

}

2:下面分別用<list/><set/><map/><props>來在配置檔案beans.xml中為集合設定引數值。

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<bean id="steelAxe" class="com.mao.collection.SteelAxe"></bean>
	<bean id="stoneAxe" class="com.mao.collection.StoneAxe"></bean>
	<bean id="chinese" class="com.mao.collection.Chinese">
	  <property name="schools">
	    <list>
	      <value>菜鳥學院</value>
	      <value>大牛學院</value>
	      <value>大神學院</value>
	    </list>
	  </property>
	  <property name="scores">
	    <map>
	      <entry key="語文" value="86"/>
	      <entry key="數學" value="95"/>
	      <entry key="英語" value="100"/>
	    </map>
	  </property>
	  <property name="phaseAxes">
	    <map>
	      <entry key="原始社會" value-ref="stoneAxe"/>
	      <entry key="農業社會" value-ref="steelAxe"/>
	    </map>
	  </property>
	  <property name="health">
	    <props>
	      <prop key="血壓">正常</prop>
	      <prop key="身高">175</prop>
	    </props>
	  </property>
	  <property name="axes">
	    <!-- 為呼叫setAxes()方法配置Set集合作為引數值 -->
			<set>
				<!-- 每個value、ref、bean..都配置一個Set元素 -->
				<value>普通的字串</value>
				<bean class="com.mao.collection.SteelAxe"/>
				<ref bean="stoneAxe"/>
				<!-- 為Set集合配置一個List集合作為元素 -->
				<list>
					<value>20</value>
					<!-- 再次為List集合配置一個Set集合作為元素 -->
					<set>
						<value type="int">30</value>
					</set>
				</list>
			</set>
	  </property>
	  <property name="books">
	    <list>
	      <value>Java從入門到精通</value>
	      <value>輕量級JavaEE企業應用實戰</value>
	      <value>經典JavaEE企業應用實戰</value>
	    </list>
	  </property>
	</bean>
	<bean id="example" class="com.mao.fuhe.Example">
	  <property name="person.name" value="VipMao"></property>
	</bean>
</beans>

Spring容器也是通過<property>的name屬性呼叫相應的setter方法,完成相應集合的賦值注入。

3:主程式 TestManager.java

package com.mao.collection;

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

public class TestManager {
	public static void main(String[]args){
		ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
		Chinese chinese=(Chinese) ctx.getBean("chinese");
		chinese.test();
	}
}

4:執行結果:


總結:

Spring框架本質就是通過xml配置檔案來驅動Java程式碼,當程式要呼叫setter方法時,總需要傳入引數值,隨著引數值不同,Spring配置檔案也要改變:

1:形參型別是基本資料型別:String ,日期等  使用value

2:形參型別是符合型別:使用ref或者巢狀Bean

3:形參型別是集合,使用<list/><set/><map/><props>來注入集合引數值