2.2.1 IoC容器的概念
IoC容器就是具有依賴注入功能的容器,IoC容器負(fù)責(zé)實(shí)例化鲜漩、定位浇坐、配置應(yīng)用程序中的對(duì)象及建立這些對(duì)象間的依賴冰肴。應(yīng)用程序無(wú)需直接在代碼中new相關(guān)的對(duì)象勺拣,應(yīng)用程序由IoC容器進(jìn)行組裝奶赠。在Spring中BeanFactory是IoC容器的實(shí)際代表者。
Spring IoC容器如何知道哪些是它管理的對(duì)象呢药有?這就需要配置文件毅戈,Spring IoC容器通過(guò)讀取配置文件中的配置元數(shù)據(jù),通過(guò)元數(shù)據(jù)對(duì)應(yīng)用中的各個(gè)對(duì)象進(jìn)行實(shí)例化及裝配愤惰。一般使用基于xml配置文件進(jìn)行配置元數(shù)據(jù)苇经,而且Spring與配置文件完全解耦的,可以使用其他任何可能的方式進(jìn)行配置元數(shù)據(jù)宦言,比如注解扇单、基于java文件的、基于屬性文件的配置都可以奠旺。
那Spring IoC容器管理的對(duì)象叫什么呢蜘澜?
2.2.2 Bean的概念
由IoC容器管理的那些組成你應(yīng)用程序的對(duì)象我們就叫它Bean, Bean就是由Spring容器初始化凉倚、裝配及管理的對(duì)象兼都,除此之外,bean就與應(yīng)用程序中的其他對(duì)象沒(méi)有什么區(qū)別了稽寒。那IoC怎樣確定如何實(shí)例化Bean扮碧、管理Bean之間的依賴關(guān)系以及管理Bean呢?這就需要配置元數(shù)據(jù)杏糙,在Spring中由BeanDefinition代表慎王,后邊會(huì)詳細(xì)介紹,配置元數(shù)據(jù)指定如何實(shí)例化Bean宏侍、如何組裝Bean等赖淤。概念知道的差不多了,讓我們來(lái)做個(gè)簡(jiǎn)單的例子谅河。
2.2.3 Hello World
一咱旱、配置環(huán)境:
JDK安裝:安裝最新的JDK,至少需要Java 1.5及以上環(huán)境;
開(kāi)發(fā)工具:SpringSource Tool Suite,簡(jiǎn)稱STS霹肝,是個(gè)基于Eclipse的開(kāi)發(fā)環(huán)境辣垒,用以構(gòu)建Spring應(yīng)用柑贞,其最新版開(kāi)始支持Spring 3.0及OSGi開(kāi)發(fā)工具,但由于其太龐大,很多功能不是我們所必需的所以我們選擇Eclipse+ SpringSource Tool插件進(jìn)行Spring應(yīng)用開(kāi)發(fā)些阅;到eclipse官網(wǎng)下載最新的Eclipse狐粱,注意我們使用的是Eclipse IDE for Java EE Developers(eclipse-jee-helios-SR1)舀寓;
安裝插件:?jiǎn)?dòng)Eclipse,選擇Help->Install New Software肌蜻,如圖2-3所示
圖2-3 安裝
2互墓、首先安裝SpringSource Tool Suite插件依賴,如圖2-4:
Name為:SpringSource Tool Suite Dependencies
Location為:http://dist.springsource.com/release/TOOLS/composite/e3.6
圖2-4 安裝
3宋欺、安裝SpringSource Tool Suite插件轰豆,只需安裝如圖2-5所選中的就可以:
Name為:SpringSource Tool Suite
Location為:http://dist.springsource.com/release/TOOLS/update/e3.6
圖2-4 安裝
4胰伍、安裝完畢齿诞,開(kāi)始項(xiàng)目搭建吧。
Spring 依賴:本書使用spring-framework-3.0.5.RELEASE
spring-framework-3.0.5.RELEASE-with-docs.zip表示此壓縮包帶有文檔的骂租;
spring-framework-3.0.5.RELEASE-dependencies.zip表示此壓縮包中是spring的依賴jar包祷杈,所以需要什么依賴從這里找就好了;
下載地址:http://www.springsource.org/download
二渗饮、開(kāi)始Spring Hello World之旅
1但汞、準(zhǔn)備需要的jar包
核心jar****包:從下載的spring-framework-3.0.5.RELEASE-with-docs.zip中dist目錄查找如下jar包
org.springframework.asm-3.0.5.RELEASE.jar
org.springframework.core-3.0.5.RELEASE.jar
org.springframework.beans-3.0.5.RELEASE.jar
org.springframework.context-3.0.5.RELEASE.jar
org.springframework.expression-3.0.5.RELEASE.jar
依賴的jar****包:從下載的spring-framework-3.0.5.RELEASE-dependencies.zip中查找如下依賴jar包
com.springsource.org.apache.log4j-1.2.15.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.commons.collections-3.2.1.jar
2、創(chuàng)建標(biāo)準(zhǔn)Java工程:
(1)選擇“window”—> “Show View” —>“Package Explorer”互站,使用包結(jié)構(gòu)視圖私蕾;
圖2-5 包結(jié)構(gòu)視圖
(2)創(chuàng)建標(biāo)準(zhǔn)Java項(xiàng)目,選擇“File”—>“New”—>“Other”胡桃;然后在彈出來(lái)的對(duì)話框中選擇“Java Project”創(chuàng)建標(biāo)準(zhǔn)Java項(xiàng)目踩叭;
圖2-6 創(chuàng)建Java項(xiàng)目
圖2-7 創(chuàng)建Java項(xiàng)目
圖2-8 創(chuàng)建Java項(xiàng)目
(3)配置項(xiàng)目依賴庫(kù)文件,右擊項(xiàng)目選擇“Properties”翠胰;然后在彈出的對(duì)話框中點(diǎn)擊“Add JARS”在彈出的對(duì)話框中選擇“l(fā)ib”目錄下的jar包容贝;然后再點(diǎn)擊“Add Library”,然后在彈出的對(duì)話框中選擇“Junit”之景,選擇“Junit4”斤富;
圖2-9 配置項(xiàng)目依賴庫(kù)文件
圖2-10 配置項(xiàng)目依賴庫(kù)文件
圖2-11 配置項(xiàng)目依賴庫(kù)文件
(4)項(xiàng)目目錄結(jié)構(gòu)如下圖所示,其中“src”用于存放java文件锻狗;“l(fā)ib”用于存放jar文件满力;“resources”用于存放配置文件;
圖2-12 項(xiàng)目目錄結(jié)構(gòu)
3轻纪、項(xiàng)目搭建好了油额,讓我們來(lái)開(kāi)發(fā)接口,此處我們只需實(shí)現(xiàn)打印“Hello World!”桐磁,所以我們定義一個(gè)“sayHello”接口悔耘,代碼如下:
java代碼:
1. package cn.javass.spring.chapter2.helloworld;
2. public interface HelloApi {
3. public void sayHello();
4. }
4、接口開(kāi)發(fā)好了我擂,讓我們來(lái)通過(guò)實(shí)現(xiàn)接口來(lái)完成打印“Hello World!”功能衬以;
java代碼:
1. package cn.javass.spring.chapter2.helloworld;
2. public class HelloImpl implements HelloApi {
3. @Override
4. public void sayHello() {
5. System.out.println("Hello World!");
6. }
7. }
5缓艳、接口和實(shí)現(xiàn)都開(kāi)發(fā)好了,那如何使用Spring IoC容器來(lái)管理它們呢看峻?這就需要配置文件阶淘,讓IoC容器知道要管理哪些對(duì)象。讓我們來(lái)看下配置文件chapter2/helloworld.xml(放到resources目錄下):
java代碼:
1. <?xml version="1.0" encoding="UTF-8"?>
2. <beans
3. xmlns="http://www.springframework.org/schema/beans"
4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5. xmlns:context="http://www.springframework.org/schema/context"
6. xsi:schemaLocation="
7. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
9. <!-- id 表示你這個(gè)組件的名字互妓,class表示組件類 -->
10. <bean id="hello" class="cn.javass.spring.chapter2.helloworld.HelloImpl"></bean>
11. </beans>
6溪窒、現(xiàn)在萬(wàn)一具備,那如何獲取IoC容器并完成我們需要的功能呢冯勉?首先應(yīng)該實(shí)例化一個(gè)IoC容器澈蚌,然后從容器中獲取需要的對(duì)象,然后調(diào)用接口完成我們需要的功能灼狰,代碼示例如下:
java代碼:
1. package cn.javass.spring.chapter2.helloworld;
2. import org.junit.Test;
3. import org.springframework.context.ApplicationContext;
4. import org.springframework.context.support.ClassPathXmlApplicationContext;
5. public class HelloTest {
6. @Test
7. public void testHelloWorld() {
8. //1宛瞄、讀取配置文件實(shí)例化一個(gè)IoC容器
9. ApplicationContext context = new ClassPathXmlApplicationContext("helloworld.xml");
10. //2、從容器中獲取Bean交胚,注意此處完全“面向接口編程份汗,而不是面向?qū)崿F(xiàn)”
11. HelloApi helloApi = context.getBean("hello", HelloApi.class);
12. //3、執(zhí)行業(yè)務(wù)邏輯
13. helloApi.sayHello();
14. }
15. }
7蝴簇、自此一個(gè)完整的Spring Hello World已完成杯活,是不是很簡(jiǎn)單,讓我們深入理解下容器和Bean吧熬词。
2.2.4 詳解IoC容器
在Spring Ioc容器的代表就是org.springframework.beans包中的BeanFactory接口旁钧,BeanFactory接口提供了IoC容器最基本功能;而org.springframework.context包下的ApplicationContext接口擴(kuò)展了BeanFactory荡澎,還提供了與Spring AOP集成均践、國(guó)際化處理、事件傳播及提供不同層次的context實(shí)現(xiàn) (如針對(duì)web應(yīng)用的WebApplicationContext)摩幔。簡(jiǎn)單說(shuō)彤委, BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 則增加了更多支持企業(yè)級(jí)功能支持或衡。ApplicationContext完全繼承BeanFactory焦影,因而B(niǎo)eanFactory所具有的語(yǔ)義也適用于ApplicationContext。
容器實(shí)現(xiàn)一覽:
? XmlBeanFactory****:BeanFactory實(shí)現(xiàn)封断,提供基本的IoC容器功能斯辰,可以從classpath或文件系統(tǒng)等獲取資源;
(1) File file = new File("fileSystemConfig.xml");
Resource resource = new FileSystemResource(file);
BeanFactory beanFactory = new XmlBeanFactory(resource);
(2)
Resource resource = new ClassPathResource("classpath.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
? ClassPathXmlApplicationContext****:ApplicationContext實(shí)現(xiàn)坡疼,從classpath獲取配置文件彬呻;
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");
? FileSystemXmlApplicationContext****:ApplicationContext實(shí)現(xiàn),從文件系統(tǒng)獲取配置文件。
BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");
具體代碼請(qǐng)參考cn.javass.spring.chapter2.InstantiatingContainerTest.java闸氮。
ApplicationContext接口獲取Bean方法簡(jiǎn)介:
? Object getBean(String name) 根據(jù)名稱返回一個(gè)Bean剪况,客戶端需要自己進(jìn)行類型轉(zhuǎn)換;
? T getBean(String name, Class<T> requiredType) 根據(jù)名稱和指定的類型返回一個(gè)Bean蒲跨,客戶端無(wú)需自己進(jìn)行類型轉(zhuǎn)換译断,如果類型轉(zhuǎn)換失敗,容器拋出異常或悲;
? T getBean(Class<T> requiredType) 根據(jù)指定的類型返回一個(gè)Bean孙咪,客戶端無(wú)需自己進(jìn)行類型轉(zhuǎn)換,如果沒(méi)有或有多于一個(gè)Bean存在容器將拋出異常巡语;
? Map<String, T> getBeansOfType(Class<T> type) 根據(jù)指定的類型返回一個(gè)鍵值為名字和值為Bean對(duì)象的 Map翎蹈,如果沒(méi)有Bean對(duì)象存在則返回空的Map。
讓我們來(lái)看下IoC容器到底是如何工作捌臊。在此我們以xml配置方式來(lái)分析一下:
一杨蛋、準(zhǔn)備配置文件:就像前邊Hello World配置文件一樣,在配置文件中聲明Bean定義也就是為Bean配置元數(shù)據(jù)理澎。
二、由IoC容器進(jìn)行解析元數(shù)據(jù): IoC容器的Bean Reader讀取并解析配置文件曙寡,根據(jù)定義生成BeanDefinition配置元數(shù)據(jù)對(duì)象糠爬,IoC容器根據(jù)BeanDefinition進(jìn)行實(shí)例化、配置及組裝Bean举庶。
三执隧、實(shí)例化IoC容器:由客戶端實(shí)例化容器,獲取需要的Bean户侥。
整個(gè)過(guò)程是不是很簡(jiǎn)單镀琉,執(zhí)行過(guò)程如圖2-5,其實(shí)IoC容器很容易使用蕊唐,主要是如何進(jìn)行Bean定義屋摔。下一章我們?cè)敿?xì)介紹定義Bean。
圖2-5 Spring Ioc容器
2.2.5 小結(jié)
除了測(cè)試程序的代碼外替梨,也就是程序入口钓试,所有代碼都沒(méi)有出現(xiàn)Spring任何組件,而且所有我們寫的代碼沒(méi)有實(shí)現(xiàn)框架擁有的接口副瀑,因而能非常容易的替換掉Spring弓熏,是不是非入侵。
客戶端代碼完全面向接口編程糠睡,無(wú)需知道實(shí)現(xiàn)類挽鞠,可以通過(guò)修改配置文件來(lái)更換接口實(shí)現(xiàn),客戶端代碼不需要任何修改。是不是低耦合信认。
如果在開(kāi)發(fā)初期沒(méi)有真正的實(shí)現(xiàn)串稀,我們可以模擬一個(gè)實(shí)現(xiàn)來(lái)測(cè)試,不耦合代碼狮杨,是不是很方便測(cè)試母截。
Bean之間幾乎沒(méi)有依賴關(guān)系,是不是很容易重用橄教。