一、Spring 概述
1.1?Spring 是分層的 Java SE/EE 應(yīng)用 full-stack 輕量級(jí)開(kāi)源框架券犁,以 IoC(Inverse Of Control: 反轉(zhuǎn)控制)和 AOP(Aspect Oriented Programming:面向切面編程)為內(nèi)核,提供了展現(xiàn)層 Spring MVC 和持久層 Spring JDBC 以及業(yè)務(wù)層事務(wù)管理等眾多的企業(yè)級(jí)應(yīng)用技術(shù),還能整合開(kāi)源世界眾多著名的第三方框架和類(lèi)庫(kù),逐漸成為使用最多的 Java EE 企業(yè)應(yīng)用開(kāi)源框架烘跺。
1.2?spring 的優(yōu)勢(shì):
1.2.1 方便解耦,簡(jiǎn)化開(kāi)發(fā):通過(guò) Spring 提供的 IoC 容器脂崔,可以將對(duì)象間的依賴關(guān)系交由 Spring 進(jìn)行控制液荸,避免硬編碼所造成的過(guò)度程序耦合。用戶也不必再為單例模式類(lèi)脱篙、屬性文件解析等這些很底層的需求編寫(xiě)代碼,可以更專(zhuān)注于上層的應(yīng)用伤柄。
1.2.2?AOP 編程的支持:通過(guò) Spring 的 AOP 功能绊困,方便進(jìn)行面向切面的編程,許多不容易用傳統(tǒng) OOP 實(shí)現(xiàn)的功能可以通過(guò)AOP輕松應(yīng)付适刀。
1.2.3 聲明式事務(wù)的支持:可以將我們從單調(diào)煩悶的事務(wù)管理代碼中解脫出來(lái)秤朗,通過(guò)聲明式方式靈活的進(jìn)行事務(wù)的管理,提高開(kāi)發(fā)效率和質(zhì)量笔喉。?
1.2.4 方便程序的測(cè)試:可以用非容器依賴的編程方式進(jìn)行幾乎所有的測(cè)試工作取视,測(cè)試不再是昂貴的操作,而是隨手可做的事情常挚。?
1.2.5 方便集成各種優(yōu)秀框架:Spring 可以降低各種框架的使用難度作谭,提供了對(duì)各種優(yōu)秀框架(Struts、Hibernate奄毡、Hessian折欠、Quartz 等)的直接支持。?
1.2.6 降低 JavaEE API 的使用難度:Spring 對(duì) JavaEE API(如 JDBC、JavaMail锐秦、遠(yuǎn)程調(diào)用等)進(jìn)行了薄薄的封裝層咪奖,使這些 API 的 使用難度大為降低。?
1.2.7 Java 源碼是經(jīng)典學(xué)習(xí)范例:Spring 的源代碼設(shè)計(jì)精妙酱床、結(jié)構(gòu)清晰羊赵、匠心獨(dú)用,處處體現(xiàn)著大師對(duì) Java 設(shè)計(jì)模式靈活運(yùn)用以及對(duì) Java 技術(shù)的高深造詣扇谣。它的源代碼無(wú)意是 Java 技術(shù)的最佳實(shí)踐的范例昧捷。
1.3?spring 的體系結(jié)構(gòu):
二、IOC的概念和作用
2.1?程序的耦合和解耦:
2.1.1 什么是程序的耦合:
?? ??? ?耦合性(Coupling)揍堕,也叫耦合度料身,是對(duì)模塊間關(guān)聯(lián)程度的度量。耦合的強(qiáng)弱取決于模塊間接口的復(fù)雜性衩茸、調(diào)用模塊的方式以及通過(guò)界面?zhèn)魉蛿?shù)據(jù)的多少芹血。模塊間的耦合度是指模塊之間的依賴關(guān)系,包括控制關(guān)系楞慈、調(diào)用關(guān)系幔烛、數(shù)據(jù)傳遞關(guān)系。模塊間聯(lián)系越多囊蓝,其耦合性越強(qiáng)饿悬,同時(shí)表明其獨(dú)立性越差( 降低耦合性,可以提高其獨(dú)立性)聚霜。
?? ??? ?在軟件工程中狡恬,耦合指的就是就是對(duì)象之間的依賴性。對(duì)象之間的耦合越高蝎宇,維護(hù)成本越高弟劲。因此對(duì)象的設(shè)計(jì)應(yīng)使類(lèi)和構(gòu)件之間的耦合最小。軟件設(shè)計(jì)中通常用耦合度和內(nèi)聚度作為衡量模塊獨(dú)立程度的標(biāo)準(zhǔn)姥芥。劃分模塊的一個(gè)準(zhǔn)則就是高內(nèi)聚低耦合兔乞。?
?? ??? ?它有如下分類(lèi):?
?? ??? ??? ?(1)內(nèi)容耦合。當(dāng)一個(gè)模塊直接修改或操作另一個(gè)模塊的數(shù)據(jù)時(shí)凉唐,或一個(gè)模塊不通過(guò)正常入口而轉(zhuǎn)入另 一個(gè)模塊時(shí)庸追,這樣的耦合被稱(chēng)為內(nèi)容耦合。內(nèi)容耦合是最高程度的耦合台囱,應(yīng)該避免使用之淡溯。?
?? ??? ??? ?(2)公共耦合。兩個(gè)或兩個(gè)以上的模塊共同引用一個(gè)全局?jǐn)?shù)據(jù)項(xiàng)簿训,這種耦合被稱(chēng)為公共耦合血筑。在具有大量公共耦合的結(jié)構(gòu)中绘沉,確定究竟是哪個(gè)模塊給全局變量賦了一個(gè)特定的值是十分困難的。?
?? ??? ??? ?(3) 外部耦合 豺总。一組模塊都訪問(wèn)同一全局簡(jiǎn)單變量而不是同一全局?jǐn)?shù)據(jù)結(jié)構(gòu)车伞,而且不是通過(guò)參數(shù)表傳遞該全局變量的信息,則稱(chēng)之為外部耦合喻喳。?
?? ??? ??? ?(4) 控制耦合 另玖。一個(gè)模塊通過(guò)接口向另一個(gè)模塊傳遞一個(gè)控制信號(hào),接受信號(hào)的模塊根據(jù)信號(hào)值而進(jìn)行適當(dāng)?shù)膭?dòng)作表伦,這種耦合被稱(chēng)為控制耦合谦去。?
?? ??? ??? ?(5)標(biāo)記耦合 。若一個(gè)模塊 A 通過(guò)接口向兩個(gè)模塊 B 和 C 傳遞一個(gè)公共參數(shù)蹦哼,那么稱(chēng)模塊 B 和 C 之間 存在一個(gè)標(biāo)記耦合鳄哭。?
?? ??? ??? ?(6) 數(shù)據(jù)耦合。模塊之間通過(guò)參數(shù)來(lái)傳遞數(shù)據(jù)纲熏,那么被稱(chēng)為數(shù)據(jù)耦合妆丘。數(shù)據(jù)耦合是最低的一種耦合形式,系統(tǒng)中一般都存在這種類(lèi)型的耦合局劲,因?yàn)闉榱送瓿梢恍┯幸饬x的功能勺拣,往往需要將某些模塊的輸出數(shù)據(jù)作為另 一些模塊的輸入數(shù)據(jù)。
?? ??? ??? ?(7) 非直接耦合 鱼填。兩個(gè)模塊之間沒(méi)有直接關(guān)系药有,它們之間的聯(lián)系完全是通過(guò)主模塊的控制和調(diào)用來(lái)實(shí)現(xiàn)的。?
?? ??? ??? ?總結(jié): 耦合是影響軟件復(fù)雜程度和設(shè)計(jì)質(zhì)量的一個(gè)重要因素苹丸,在設(shè)計(jì)上我們應(yīng)采用以下原則:如果模塊間必須存在耦合愤惰,就盡量使用數(shù)據(jù)耦合,少用控制耦合赘理,限制公共耦合的范圍宦言,盡量避免使用內(nèi)容耦合。?
?? ??? ??? ?內(nèi)聚與耦合:內(nèi)聚標(biāo)志一個(gè)模塊內(nèi)各個(gè)元素彼此結(jié)合的緊密程度感憾,它是信息隱蔽和局部化概念的自然擴(kuò)展。內(nèi)聚是從功能角度來(lái)度量模塊內(nèi)的聯(lián)系令花,一個(gè)好的內(nèi)聚模塊應(yīng)當(dāng)恰好做一件事阻桅。它描述的是模塊內(nèi)的功能聯(lián)系。耦合是軟件結(jié)構(gòu)中各模塊之間相互連接的一種度量兼都,耦合強(qiáng)弱取決于模塊間接口的復(fù)雜程度嫂沉、進(jìn)入或訪問(wèn)一個(gè)模塊的點(diǎn)以及通過(guò)接口的數(shù)據(jù)。程序講究的是低耦合扮碧,高內(nèi)聚趟章。就是同一個(gè)模塊內(nèi)的各個(gè)元素之間要高度緊密杏糙,但是各個(gè)模塊之間的相互依存度卻要不那么緊密。?
2.1.2 工廠模式解耦:在實(shí)際開(kāi)發(fā)中我們可以把三層的對(duì)象都使用配置文件配置起來(lái)蚓土,當(dāng)啟動(dòng)服務(wù)器應(yīng)用加載的時(shí)候宏侍,讓一個(gè)類(lèi)中的方法通過(guò)讀取配置文件,把這些對(duì)象創(chuàng)建出來(lái)并存起來(lái)蜀漆。在接下來(lái)的使用的時(shí)候谅河,直接拿過(guò)來(lái)用就好了。 那么确丢,這個(gè)讀取配置文件绷耍,創(chuàng)建和獲取三層對(duì)象的類(lèi)就是工廠。
2.1.3 控制反轉(zhuǎn)-Inversion Of Control:?
上一小節(jié)解耦的思路有 2 個(gè)問(wèn)題:
?? ??? ?1鲜侥、創(chuàng)建出來(lái)的對(duì)象要存到哪里去褂始??我們的答案就是在應(yīng)用加載時(shí),創(chuàng)建一個(gè) Map描函,用于存放三層對(duì)象崎苗。我們把這個(gè)map稱(chēng)之為容器。?
?? ??? ?2赘阀、到底什么是工廠益缠? 工廠就是負(fù)責(zé)給我們從容器中獲取指定對(duì)象的類(lèi)。這時(shí)候我們獲取對(duì)象的方式發(fā)生了改變基公。?
?? ??? ??? ?原來(lái): 我們?cè)讷@取對(duì)象都是采用new的方式幅慌,是主動(dòng)的。?
?? ??? ??? ?現(xiàn)在: 我們獲取對(duì)象時(shí)就有工廠為我們查找或者創(chuàng)建對(duì)象轰豆,是被動(dòng)的胰伍。
總結(jié):這種被動(dòng)接收的方式獲取對(duì)象的思想就是控制反轉(zhuǎn)ioc,它是spring框架的核心之一酸休。?ioc 的作用就是削減計(jì)算機(jī)程序的耦合(解除我們代碼中的依賴關(guān)系)骂租。
三、使用 spring 的 IOC 解決程序耦合
3.1?使用spring的環(huán)境搭建:
3.1.1?準(zhǔn)備 spring 的開(kāi)發(fā)包:
官網(wǎng):http://spring.io/?
下載地址:http://repo.springsource.org/libs-release-local/org/springframework/spring
3.1.2 解壓spring開(kāi)發(fā)包了并解spring的目錄結(jié)構(gòu):?
?? ??? ??? ??? ?docs:API 和開(kāi)發(fā)規(guī)范?
?? ??? ??? ??? ?libs:jar 包和源碼?
?? ??? ??? ??? ?schema:約束?
3.1.3 創(chuàng)建業(yè)務(wù)層接口和實(shí)現(xiàn)類(lèi)
3.1.4 創(chuàng)建持久層接口和實(shí)現(xiàn)類(lèi)
3.2 基于 XML 的spring使用案例配置
3.2.1 第一步:拷貝必備的 jar 包到工程的 lib 目錄中
3.2.2?第二步:在類(lèi)的根路徑下創(chuàng)建一個(gè)任意名稱(chēng)的 xml 文件(不能是中文)
給配置文件導(dǎo)入約束:
3.2.3?第三步:讓 spring 管理資源斑司,在配置文件中配置 service 和 dao
3.2.4?測(cè)試配置是否成功
3.3 Spring 基于 XML 的 IOC 細(xì)節(jié):
3.3.1 BeanFactory 和 ApplicationContext 的區(qū)別:
BeanFactory才是Spring容器中的頂層接口渗饮,ApplicationContext 是它的子接口。?
BeanFactory和ApplicationContext 的區(qū)別: 創(chuàng)建對(duì)象的時(shí)間點(diǎn)不一樣宿刮。 ApplicationContext:只要一讀取配置文件互站,默認(rèn)情況下就會(huì)創(chuàng)建對(duì)象。 BeanFactory:什么使用什么時(shí)候創(chuàng)建對(duì)象僵缺。
3.3.2 ApplicationContext 接口的實(shí)現(xiàn)類(lèi):
ClassPathXmlApplicationContext:它是從類(lèi)的根路徑下加載配置文件推薦使用這種 FileSystemXmlApplicationContext:它是從磁盤(pán)路徑上加載配置文件胡桃,配置文件可以在磁盤(pán)的任意位置。?
AnnotationConfigApplicationContext: 當(dāng)我們使用注解配置容器對(duì)象時(shí)磕潮,需要使用此類(lèi)來(lái)創(chuàng)建 spring 容器翠胰。它用來(lái)讀取注解
3.3.3 IOC 中 bean 標(biāo)簽和管理對(duì)象細(xì)節(jié):
3.3.3.1 bean標(biāo)簽的屬性和作用:
作用: 用于配置對(duì)象讓 spring 來(lái)創(chuàng)建的容贝。?
?? ??? ??? 默認(rèn)情況下它調(diào)用的是類(lèi)中的無(wú)參構(gòu)造函數(shù)。如果沒(méi)有無(wú)參構(gòu)造函數(shù)則不能創(chuàng)建成功之景。?
屬性:?
?? ??? ?id:給對(duì)象在容器中提供一個(gè)唯一標(biāo)識(shí)斤富。用于獲取對(duì)象。?
?? ?? ??class:指定類(lèi)的全限定類(lèi)名闺兢,用于反射創(chuàng)建對(duì)象茂缚,默認(rèn)調(diào)用無(wú)參構(gòu)造函數(shù)。?
?? ??? ?scope:指定對(duì)象的作用范圍屋谭。?
?? ??? ??? ??? ?* singleton:默認(rèn)值脚囊,單例的
?? ??? ??? ??? ?* prototype:多例的?
?? ??? ??? ??? ?* request:WEB 項(xiàng)目中,Spring 創(chuàng)建一個(gè) Bean 的對(duì)象,
?? ??? ??? ??? ??? ??? ??? ??? ???將對(duì)象存入到 request 域中
?? ??? ??? ??? ?* session:WEB 項(xiàng)目中,Spring 創(chuàng)建一個(gè) Bean 的對(duì)象,
?? ??? ??? ??? ??? ??? ??? ?? ? ??將對(duì)象存入到 session 域中.?
?? ??? ??? ??? ?* global session:WEB 項(xiàng)目中,應(yīng)用在 Portlet 環(huán)境.如果沒(méi)有 Portlet 環(huán)?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?境那么 globalSession 相當(dāng)于 session
?? ??? ?init-method:指定類(lèi)中的初始化方法名稱(chēng)。?
?? ??? ?destroy-method:指定類(lèi)中銷(xiāo)毀方法名稱(chēng)桐磁。
3.3.3.2 bean 的作用范圍和生命周期:
單例對(duì)象:scope="singleton"
?? ??? ??一個(gè)應(yīng)用只有一個(gè)對(duì)象的實(shí)例悔耘。它的作用范圍就是整個(gè)引用。?
?? ?? ? ?生命周期:?
?? ??? ??? ??? ??? ?對(duì)象出生:當(dāng)應(yīng)用加載我擂,創(chuàng)建容器時(shí)衬以,對(duì)象就被創(chuàng)建了。?
?? ??? ??? ??? ??? ?對(duì)象活著:只要容器在校摩,對(duì)象一直活著看峻。?
?? ??? ??? ??? ??? ?對(duì)象死亡:當(dāng)應(yīng)用卸載,銷(xiāo)毀容器時(shí)衙吩,對(duì)象就被銷(xiāo)毀了互妓。?
多例對(duì)象:scope="prototype"?
?? ??? ?每次訪問(wèn)對(duì)象時(shí),都會(huì)重新創(chuàng)建對(duì)象實(shí)例坤塞。?
?? ??? ?生命周期:?
?? ??? ??? ??? ??? ?對(duì)象出生:當(dāng)使用對(duì)象時(shí)冯勉,創(chuàng)建新的對(duì)象實(shí)例。?
?? ??? ??? ??? ??? ?對(duì)象活著:只要對(duì)象在使用中摹芙,就一直活著灼狰。?
?? ??? ??? ??? ??? ?對(duì)象死亡:當(dāng)對(duì)象長(zhǎng)時(shí)間不用時(shí),被 java 的垃圾回收器回收了浮禾。
3.3.3.3 實(shí)例化 Bean 的三種方式:
第一種方式:使用默認(rèn)無(wú)參構(gòu)造函數(shù)交胚,在默認(rèn)情況下,它會(huì)根據(jù)默認(rèn)無(wú)參構(gòu)造函數(shù)來(lái)創(chuàng)建類(lèi)對(duì)象盈电。如果 bean 中沒(méi)有默認(rèn)無(wú)參構(gòu)造函數(shù)蝴簇,將會(huì)創(chuàng)建失敗。
第二種方式:spring 管理靜態(tài)工廠-使用靜態(tài)工廠的方法創(chuàng)建對(duì)象:
第三種方式:spring 管理實(shí)例工廠挣轨,使用實(shí)例工廠的方法創(chuàng)建對(duì)象:
3.3.4 spring 的依賴注入
3.3.4.1 依賴注入的概念:依賴注入是 spring 框架核心 ioc 的具體實(shí)現(xiàn)军熏。 我們的程序在編寫(xiě)時(shí)轩猩,通過(guò)控制反轉(zhuǎn)卷扮,把對(duì)象的創(chuàng)建交給了 spring荡澎,但是代碼中不可能出現(xiàn)沒(méi)有依賴的情況。 ioc 解耦只是降低他們的依賴關(guān)系晤锹,但不會(huì)消除摩幔。例如:我們的業(yè)務(wù)層仍會(huì)調(diào)用持久層的方法。 那這種業(yè)務(wù)層和持久層的依賴關(guān)系鞭铆,在使用 spring 之后或衡,就讓 spring 來(lái)維護(hù)了。 簡(jiǎn)單的說(shuō)车遂,就是坐等框架把持久層對(duì)象傳入業(yè)務(wù)層封断,而不用我們自己去獲取。
3.3.4.2 構(gòu)造函數(shù)注入:顧名思義舶担,就是使用類(lèi)中的構(gòu)造函數(shù)坡疼,給成員變量賦值。注意衣陶,賦值的操作不是我們自己做的柄瑰,而是通過(guò)配置的方式,讓 spring 框架來(lái)為我們注入剪况。涉及的標(biāo)簽: constructor-arg??配置方式如下:
3.3.4.3 set 方法注入:顧名思義教沾,就是在類(lèi)中提供需要注入成員的 set 方法,然后通過(guò)配置文件給 bean 中的屬性傳值译断,使用 set 方法的方式授翻,涉及的標(biāo)簽: property
3.3.4.5 注入集合屬性:顧名思義,就是給類(lèi)中的集合成員傳值镐作,它用的也是set方法注入的方式藏姐,只不過(guò)變量的數(shù)據(jù)類(lèi)型都是集合。?