1. 程式人生 > >Spring IOC 依賴注入( 二 )

Spring IOC 依賴注入( 二 )

目錄

圖解:

流程圖解:

圖解流程:

1、什麼是IOC

IOC 全稱指的是 Inverse Of Control 控制反轉。

原來我們使用Spring之前物件都是通過程式碼 new 物件()來自己進行建立。

現在使用了Spring之後。只需要在Spring的配置檔案中進行配置,那麼spring就會幫我們new出物件來。

2、什麼是DI

DI 指的是Dependency Injection 。是依賴注入的意思。

BookService{
    BookDao bookDao;

    public void setBookDao( BookDao bookDao ){
        this.bookDao = bookDao;
    }
}

只需要配置就可以把依賴的物件的值注入到引用中。

3、第一個IOC示例程式 -- 通過id獲取物件(重點)

實驗1:通過IOC容器建立物件,併為屬性賦值★

1、建立一個Java工程:

建立相應的類

person類程式碼

為節省空間,省略get\set方法,toString不寫

package com.webcode.pojo;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/** * @author Administrator *
 */
public class Person {	

	private Integer id;
	private String name;
	private Integer age;
	private String phone;
	private Car car;
	
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Person(Integer id, String name, Integer age, String phone, Car car) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.phone = phone;
		this.car = car;
	}
	

Car 類的程式碼

public class Car {
	
/*
    省略 get\set方法 和 toString方法不寫
*/
	private String name;
	private String carNo;
	public Car() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Car(String name, String carNo) {
		super();
		this.name = name;
		this.carNo = carNo;
	}
}

2、匯入jar包:

  • commons-logging-1.1.3.jar
  • log4j-1.2.17.jar
  • spring-beans-4.3.18.RELEASE.jar
  • spring-context-4.3.18.RELEASE.jar
  • spring-core-4.3.18.RELEASE.jar
  • spring-expression-4.3.18.RELEASE.jar

applicationContext.xml配置檔案內容如下:

<!-- 
	bean標籤標識要配置一個bean物件
	class 屬性配置你要陪哪個Bean物件的全類名
	id 屬性給配置的Bean物件起一個唯一標識
 -->
	<bean id="p1" class="com.webcode.pojo.Person">
		<!-- 
			property 標籤配置屬性的值
				name 標識你要配置哪個屬性
				value 屬性配置這個屬性的值
	 	-->
	 	<property name="id" value="1"></property>
	 	<property name="name" value="旻"></property>
		<property name="age" value="25"></property>
 		<property name="phone" value="148999999"></property>
	</bean>

測試的程式碼:

        @Test
	public void test1()throws Exception {
		//ApplicationContext 表示SpringIOC 容器
		ApplicationContext applicationContext  =  new ClassPathXmlApplicationContext("applicationContext.xml");
		//使用了Spring之後。物件都交給Spring視窗來建立和管理
		//Spring 容器就是一個map,然後id是key class 時哪個value
		Person person = (Person) applicationContext.getBean("p1");
		System.out.println(person);
	}

列印結果:

問題:

1、FileSystemXmlApplicationContext怎麼用?

答:跟使用JavaSE的相對路徑一樣

2、Bean是在什麼時候被建立的?

答:在建立Spring容器的時候,建立Bean物件(預設)

  1. 如果呼叫getBean多次,會建立幾個?

答:預設建立同一個

常見的錯誤:

指定的id不存在。找不到bean物件。

4、IOC示例程式 -- 通過型別獲取物件(重點)

實驗2:根據bean的型別從IOC容器中獲取bean的例項★

配置檔案程式碼:

	<bean id="p2" class="com.webcode.pojo.Person" >
		<!-- 	property 標籤配置屬性的值
				name 標識你要配置哪個屬性
				value 屬性配置這個屬性的值 -->
	 	
	 	<property name="id" value="2"></property>
	 	<property name="name" value="旻"></property>
		<property name="age" value="25"></property>
 		<property name="phone" value="148999999"></property>
	</bean>
      @Test
      public void test2()throws Exception{
		ApplicationContext applicationContext =new ClassPathXmlApplicationContext("applicationContext.xml");
		
		 * 
		 * 按型別查詢,找到一個就直接返回
		 * 沒有找到就報錯
		 * 找到多個也報錯
		 * 
		System.out.println(applicationContext.getBean(Person.class));
	}

常見錯誤說明:

按型別查詢,找不到就報錯

當在applicationContext.xml配置檔案中。有多個同Person.class型別實現的時候。

5、IOC示例程式 -- 通過構造方法引數名注入值

實驗3:通過構造器為bean的屬性賦值

        <bean id="p3" class="com.webcode.pojo.Person">
		
		<!-- 	constructor-arg 是按構造器引數賦值
				name	給哪個屬性賦值
				value	傳遞的引數值 -->
		
		<constructor-arg name="name" value="王玄策" />
		<constructor-arg name="id" value="3" />
		<constructor-arg name="age" value="38" />
		<constructor-arg name="phone" value="198745632" />
	</bean>  

測試程式碼:

        @Test
	public void test3()throws Exception{
		 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		 System.out.println(applicationContext.getBean("p3"));
	}

列印結果:

6、IOC示例程式 -- index屬性指定引數的位置

實驗4:通過index屬性指定引數的位置

        <bean id="p4" class="com.webcode.pojo.Person">
		
			<!-- constructor-arg 是按構造器引數賦值
				name	給哪個屬性賦值
				value	傳遞的引數值 -->
		
		<constructor-arg index="1" value="大漢光武" />
		<constructor-arg index="0" value="4" />
		<constructor-arg index="2" value="26" />
		<constructor-arg index="3" value="1888951233" />
	</bean> 

測試程式碼:

        @Test
	public void test4()throws Exception{
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		System.out.println(applicationContext.getBean("p4"));
	}

列印結果:

7、IOC示例程式 -- 根據引數型別注入

實驗5:根據引數型別注入


	public Person(Integer id, String name, Integer age, String phone) {
		super();
		System.out.println("建立了Person==有參");
		this.id = id;
		this.name = name;
		this.age = age;
		this.phone = phone;
	}
	
	public Person(Integer id, String name, String phone,Integer age) {
		super();
		System.out.println("建立了Person==有參");
		this.id = id;
		this.name = name;
		this.age = age;
		this.phone = phone;
	}

配置資訊:

        <bean id="p5" class="com.webcode.pojo.Person">
		<!-- Integer id, String name, Integer age, String phone
		
			constructor-arg 是按構造器引數賦值
				index	構造引數的索引
				value	傳遞的引數值 -->
		
		 <constructor-arg index="0" value="4" type="java.lang.Integer"></constructor-arg>
		 <constructor-arg index="1" value="帥才" type="java.lang.String"></constructor-arg>
		 <constructor-arg index="2" value="19" type="java.lang.Integer"></constructor-arg>
		 <constructor-arg index="3" value="18" type="java.lang.String"></constructor-arg>
		
	</bean> 

測試程式碼:

        @Test
	public void test5()throws Exception{
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		System.out.println(applicationContext.getBean("p5"));
	}

列印結果:

8、IOC之 P名稱空間

實驗6:通過p名稱空間為bean賦值

配置資訊:

		<!-- p名稱空間是同過set方法複製 -->
	
	<bean id="p6" class="com.webcode.pojo.Person"
		p:id="6"  p:age="25" p:name="旻"  p:phone="145665389">
				
	</bean>

測試程式碼:

        @Test
	public void test6()throws Exception{
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		System.out.println(applicationContext.getBean("p6"));
	}

列印結果:

9、測試null值的使用

實驗7:測試使用null值

配置資訊:

        <!-- 測試null值的應用 -->
	<bean id="p7 " class="com.webcode.pojo.Person">
		<property name="id" value="7"></property>
		<property name="name"><null></null></property>
	</bean>

測試程式碼:

	@Test
	public void test7() throws Exception {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person = (Person) applicationContext.getBean("p7");
		System.out.println( person.getName().length() );
	}

10、IOC之子物件的賦值測試(重點)

實驗8:引用其他bean★

建立個新的工程。測試Spring的開發環境。此不重複。請參閱前面,環境搭建。

Car物件

public class Car {

	private String name;
	private String carNo;

public class Person {

	private Integer id;
	private String name;
	private Integer age;
	private String phone;
	private Car car;

配置資訊:

        <bean id="car" class="com.webcode.pojo.Car" p:name="寶馬" p:carNo="京B123412"/>

	<bean id="p8" class="com.webcode.pojo.Person">
		<property name="id" value="8" />
		<!-- 
			car屬性,可以通過ref(引用的意思)某個指定id值的物件
		 -->
		<property name="car" ref="car" />
	</bean>

測試程式碼:

	@Test
	public void test8() throws Exception {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person = (Person) applicationContext.getBean("p8");
		System.out.println( person );
	}

列印結果:

11、IOC之內部Bean的使用

實驗9:引用內部bean

配置資訊:

        <!--  引用內部bean -->
	<bean id="p9" class="com.webcode.pojo.Person">
		<property name="id" value="9"></property>
		<property name="car">
			<!-- 內部bean ,不能被外部使用 -->
			<bean id="car02" class="com.webcode.pojo.Car"  p:name="內部car" p:carNo="京B123422" />
		</property>
	</bean>

測試程式碼:

        @Test
	public void test9() throws Exception {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person = (Person) applicationContext.getBean("p9");
		System.out.println( person );
		System.out.println( applicationContext.getBean("car02") );
	}

列印結果:

常見錯誤:內部的Bean不能被外部使用

12、IOC之List屬性的賦值

實驗10:使用list子元素為List型別的屬性賦值

Person物件

配置的資訊:

        <bean id="p10" class="com.webcode.pojo.Person">
		<property name="id" value="9"></property>
		<property name="list">
			<!-- list標籤,表示當前配置一個list集合 -->
			<list>
				<value>文</value>
				<value>星</value>
				<value>念</value>
			</list>
		</property>
	</bean>

------------------------------------------  此處省略測試程式碼!

列印結果

13、IOC之Map屬性的賦值

實驗11:使用map子元素為Map型別的屬性賦值

配置資訊:

        <!-- 實驗11:使用map子元素為Map型別的屬性賦值 -->
	<bean id="p11" class="com.webcode.pojo.Person">
		<property name="id" value="9"></property>
		<property name="map">
			<!-- map標籤,表示當前配置一個map集合 -->
			<map>
				<entry key="key1" value="遠方"></entry>
				<entry key="key2" value="流星"></entry>
				<entry key="key3" value-ref="car"></entry>			
			</map>
		</property>
	</bean>

------------------------------------------  此處省略測試程式碼!

列印結果:

14、IOC之Properties屬性的賦值

實驗12:使用prop子元素為Properties型別的屬性賦值

配置資訊:

        <!-- 實驗12:使用prop子元素為Properties型別的屬性賦值 -->
	<bean id="p12" class="com.webcode.pojo.Person">
		<property name="id" value="9"></property>
		<property name="map">
			<!-- props標籤,表示當前配置一個Properties -->
			<props>
				<prop key="user">root</prop>
				<prop key="password">123456</prop>
			</props>
		</property>
	</bean>

------------------------------------------  此處省略測試程式碼!

列印結果:

15、IOC之util 名稱空間

util名稱空間,可以定義

實驗13:通過util名稱空間建立集合型別的bean

配置資訊:

        <!--  util名稱空間引用,可以定義
		實驗13:通過util名稱空間建立集合型別的bean-->
		<!-- 定義一個list集合 -->
	<util:list id="list1">
		<value>string1</value>
		<value>string2</value>
		<value>string3</value>	
	</util:list>	
	<bean id="p13" class="com.webcode.pojo.Person">
		<property name="id" value="13"></property>
		<property name="name" value="旻"></property>
		<property name="age" value="24"></property>
		<property name="phone" value="1722235896"></property>
		<!-- list物件 ref表示引用 -->
		<property name="phones" ref="list1"></property>
	</bean>

測試程式碼:

        @Test
	public void test13()throws Exception{
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person = (Person) applicationContext.getBean("p13");
		System.out.println( person );
		
		List<String> list = (List<String>) applicationContext.getBean("list1");
		System.out.println(list);
	}

列印結果:

圖解:

16、IOC之級聯屬性賦值

實驗14:給bean的級聯屬性賦值

配置:

        <!-- 實驗14:給bean的級聯屬性賦值	 
			常見錯誤:
		級聯屬性一定要先注入物件。再注入物件的屬性
	-->
	<bean id="p14" class="com.webcode.pojo.Person">
	 	<property name="id" value="14"></property>
	 	<property name="name" value="星"></property>
	 	<property name="age" value="27"></property>
	 	<property name="phone" value="17889652345"></property>
	 	<!-- list物件 ref 表示引用 -->
	 	<property name="car" ref="car"></property>
	 	<!-- -級聯屬性 -->
	 	<property name="car.name" value="凱迪拉克"></property>
	</bean>

------------------------------------------  此處省略測試程式碼!

列印結果:

常見錯誤:

級聯屬性一定要先注入物件。再注入物件的屬性

圖解:

17、IOC之靜態工廠方法建立Bean

實驗15:配置通過靜態工廠方法建立的bean

程式碼:

    public class PersonFactory {
	public static Person createPerson() {
		return new Person(1, "我是靜態工廠方法創建出來的", 18, "18688886666");
	}
    }

配置資訊:

        <!-- 靜態工廠方法呼叫建立物件	
			factory-method 是指呼叫哪個方法返回物件 -->
	
	<bean id="p15" class="com.webcode.pojo.factory.PersonFactory"
		factory-method="createPerson"/>

------------------------------------------  此處省略測試程式碼!

圖解:

不重寫toString方法的情況下,地址值相同,呼叫的是同一個物件,從工廠中的方法獲取

建立物件流程:

18、IOC之工廠例項方法建立Bean

實驗16:配置通過例項工廠方法建立的bean

    public class PersonFactory {

	public Person createPerson2() {
		return new Person(1, "我是工廠例項方法創建出來的", 18, "18688886666");
	}
	
    }

配置資訊:

        <!-- 配置工廠例項 -->
	<bean id="personFactory" class="com.webcode.pojo.factory.PersonFactory"/>
	<!-- 
		factory-bean="personFactory" 	表示準備呼叫哪個例項的方法
		factory-method="createFacroty2"  是指呼叫哪個方法  	
	 -->
	 <bean id="p16" factory-bean="personFactory" factory-method="createPerson2">            </bean>
	

------------------------------------------  此處省略測試程式碼!

列印結果:

流程圖解:

19、IOC之FactoryBean介面方式建立物件

實驗17:配置FactoryBean介面建立Bean物件

FactoryBean介面方式

package com.webcode.pojo.factory;
import org.springframework.beans.factory.FactoryBean;
import com.webcode.pojo.Person;
    public class PersonFactoryBean implements FactoryBean<Person> {	
	/*
	 * 建立物件例項的適合,呼叫的方法
	 * */
	@Override
	public Person getObject() throws Exception {		
		return new Person(1,"我是PersonFactoryBean類",18,"14568526666");
	}	
	/*
	 * 返回物件的型別,相當於class屬性
	 * */
	@Override
	public Class<?> getObjectType() {		
		return Person.class;
	}	
	/*
	 * 是否是單例
	 * */
	@Override
	public boolean isSingleton() {
		return true;
	}		
}

配置資訊:

        <!-- 
		建立一個工廠例項物件FactoryBean介面的實現類
	 -->
	<bean id="p17" class="com.webcode.pojo.factory.PersonFactoryBean"/>

------------------------------------------  此處省略測試程式碼!

列印結果:

圖解流程:

20、IOC之繼承Bean配置

實驗18:通過繼承實現bean配置資訊的重用

配置資訊:

        <!-- 實驗18:通過繼承實現bean配置資訊的重用 -->
		<bean id="parent" class="com.webcode.pojo.Person">
		<property name="id" value="100"></property>
		<property name="name" value="我思念的人啊"></property>
		<property name="age" value="24"></property>
		<property name="phone" value="1477888999"></property>	
	</bean>
	<!-- parent="parent" 繼承指定的parentid的bean物件的配置資訊-->
	<bean id="p18" class="com.webcode.pojo.Person" parent="parent">
		<property name="id" value="18"></property>
	</bean>

------------------------------------------  此處省略測試程式碼!

列印結果:

圖解:先比較parent與id是否相同,再拿class進行比較,

注意:當有兩個id相同,而型別不同的bean存在時,會出現ReaderContext.error讀取異常