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物件(預設)
- 如果呼叫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讀取異常