Spring學(xué)習筆記:第一章 Spring的下載和安裝
第二章 Spring中IoC的入門(mén)實(shí)例
Spring的模塊化是很強的,各個(gè)功能模塊都是獨立的,我們可以選擇的使用。這一章先從Spring的IoC開(kāi)始。所謂IoC就是一個(gè)用XML來(lái)定義生成對象的模式,我們看看如果來(lái)使用的。
1、如下圖所示有三個(gè)類(lèi),Human(人類(lèi))是接口,Chinese(中國人)是一個(gè)子類(lèi),American(美國人)是另外一個(gè)子類(lèi)。

源代碼如下:
package cn.com.chengang.spring;
public interface Human {
void eat();
void walk();
}
package cn.com.chengang.spring;
public class Chinese implements Human {
/* (非 Javadoc)
* @see cn.com.chengang.spring.Human#eat()
*/
public void eat() {
System.out.println("中國人對吃很有一套");
}
/* (非 Javadoc)
* @see cn.com.chengang.spring.Human#walk()
*/
public void walk() {
System.out.println("中國人行如飛");
}
}
package cn.com.chengang.spring;
public class American implements Human {
/* (非 Javadoc)
* @see cn.com.chengang.spring.Human#eat()
*/
public void eat() {
System.out.println("美國人主要以面包為主");
}
/* (非 Javadoc)
* @see cn.com.chengang.spring.Human#walk()
*/
public void walk() {
System.out.println("美國人以車(chē)代步,有四肢退化的趨勢");
}
}
創(chuàng )建一個(gè)工廠(chǎng)類(lèi)Factory,如下。這個(gè)工廠(chǎng)類(lèi)里定義了兩個(gè)字符串常量,所標識不同的人種。getHuman方法根據傳入參數的字串,來(lái)判斷要生成什么樣的人種。
package cn.com.chengang.spring;
public class Factory {
public final static String CHINESE = "Chinese";
public final static String AMERICAN = "American";
public Human getHuman(String ethnic) {
if (ethnic.equals(CHINESE))
return new Chinese();
else if (ethnic.equals(AMERICAN))
return new American();
else
throw new IllegalArgumentException("參數(人種)錯誤");
}
}
下面是一個(gè)測試的程序,使用工廠(chǎng)方法來(lái)得到了不同的"人種對象",并執行相應的方法。
package cn.com.chengang.spring;
public class ClientTest {
public static void main(String[] args) {
Human human = null;
human = new Factory().getHuman(Factory.CHINESE);
human.eat();
human.walk();
human = new Factory().getHuman(Factory.AMERICAN);
human.eat();
human.walk();
}
}
控制臺的打印結果如下:

1、在項目根目錄下創(chuàng )建一個(gè)bean.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="Chinese" class="cn.com.chengang.spring.Chinese"/>
<bean id="American" class="cn.com.chengang.spring.American"/>
</beans>
bean.xml的位置如下圖,注意不要看花眼把它看成是lib目錄下的了,它是在myspring目錄下的。

2、修改ClientTest程序如下:
package cn.com.chengang.spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class ClientTest {
public final static String CHINESE = "Chinese";
public final static String AMERICAN = "American";
public static void main(String[] args) {
// Human human = null;
// human = new Factory().getHuman(Factory.CHINESE);
// human.eat();
// human.walk();
// human = new Factory().getHuman(Factory.AMERICAN);
// human.eat();
// human.walk();
ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
Human human = null;
human = (Human) ctx.getBean(CHINESE);
human.eat();
human.walk();
human = (Human) ctx.getBean(AMERICAN);
human.eat();
human.walk();
}
}
從這個(gè)程序可以看到,ctx就相當于原來(lái)的Factory工廠(chǎng),原來(lái)的Factory就可以刪除掉了。然后又把Factory里的兩個(gè)常量移到了ClientTest類(lèi)里,整個(gè)程序結構基本一樣。
再回頭看原來(lái)的bean.xml文件的這一句
<bean id="Chinese" class="cn.com.chengang.spring.Chinese"/>
id就是ctx.getBean的參數值,一個(gè)字符串。class就是一個(gè)類(lèi)(包名+類(lèi)名)。然后在ClientTest類(lèi)里獲得Chinese對象就是這么一句
human = (Human) ctx.getBean(CHINESE);
因為getBean方法返回的是Object類(lèi)型,所以前面要加一個(gè)類(lèi)型轉換。
(1)也許有人說(shuō),IoC和工廠(chǎng)模式不是一樣的作用嗎,用IoC好象還麻煩一點(diǎn)。
舉個(gè)例子,如果用戶(hù)需求發(fā)生變化,要把Chinese類(lèi)修改一下。那么前一種工廠(chǎng)模式,就要更改Factory類(lèi)的方法,并且重新編譯布署。而IoC只需要將class屬性改變一下,并且由于IoC利用了Java反射機制,這些對象是動(dòng)態(tài)生成的,這時(shí)我們就可以熱插撥Chinese對象(不必把原程序停止下來(lái)重新編譯布署)
(2)也許有人說(shuō),即然IoC這么好,那么我把系統所有對象都用IoC方式來(lái)生成。
注意,IoC的靈活性是有代價(jià)的:設置步驟麻煩、生成對象的方式不直觀(guān)、反射比正常生成對象在效率上慢一點(diǎn)。因此使用IoC要看有沒(méi)有必要,我認為比較通用的判斷方式是:用到工廠(chǎng)模式的地方都可以考慮用IoC模式。
(3)在上面的IoC的方式里,還有一些可以變化的地方。比如,bean.xml不一定要放在項目錄下,也可以放在其他地方,比如cn.com.chengang.spring包里。不過(guò)在使用時(shí)也要變化一下,如下所示:
new FileSystemXmlApplicationContext("src/cn/com/chengang/spring/bean.xml");
另外,bean.xml也可以改成其他名字。這樣我們在系統中就可以分門(mén)別類(lèi)的設置不同的bean.xml。
(4)關(guān)于IoC的低侵入性。
什么是低侵入性?如果你用過(guò)Struts或EJB就會(huì )發(fā)現,要繼承一些接口或類(lèi),才能利用它們的框架開(kāi)發(fā)。這樣,系統就被綁定在Struts、EJB上了,對系統的可移植性產(chǎn)生不利的影響。如果代碼中很少涉及某一個(gè)框架的代碼,那么這個(gè)框架就可以稱(chēng)做是一個(gè)低侵入性的框架。
Spring的侵入性很低,Humen.java、Chinese.java等幾個(gè)類(lèi)都不必繼承什么接口或類(lèi)。但在ClientTest里還是有一些Spring的影子:FileSystemXmlApplicationContext類(lèi)和ctx.getBean方式等。
現在,低侵入性似乎也成了判定一個(gè)框架的實(shí)現技術(shù)好壞的標準之一。
(5)關(guān)于bean.xml的用法
bean.xml的用法還有很多,其中內容是相當豐富的。假設Chinese類(lèi)里有一個(gè)humenName屬性(姓名),那么原的bean.xml修改如下。此后生成Chinese對象時(shí),"陳剛"這個(gè)值將自動(dòng)設置到Chinese類(lèi)的humenName屬性中。而且由于singleton為true這時(shí)生成Chinese對象將采用單例模式,系統僅存在一個(gè)Chinese對象實(shí)例。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="Chinese" class="cn.com.chengang.spring.Chinese" singleton="true">
<property name="humenName">
<value>陳剛</value>
</property>
</bean>
<bean id="American" class="cn.com.chengang.spring.American"/>
</beans>
關(guān)于bean.xml的其它用法,不再詳細介紹了,大家自己拿Spring的文檔一看就明白了。
聯(lián)系客服