在網上看到一篇文章,感覺寫得挺不錯的,轉載一下,本文轉載自:http://www.cnblogs.com/xdp-gacl/p/3707631.html和http://www.cnblogs.com/xdp-gacl/p/4249939.html
什么是Spring
Spring產生於2003年, Spring是一個分層的JavaSE/EEfull-stack(一站式) 輕量級開源框架。
spring的優點
A. 方便解耦,簡化開發(高內聚,低耦合)
Spring就是一個大工廠(容器),可以將所有對象創建和依賴關系維護,交給Spring管理
B. AOP編程的支持
Spring提供面向切面編程,可以方便的實現對程序進行權限攔截、運行監控等功能
C. 聲明式事務的支持
只需要通過配置就可以完成對事務的管理,而無需手動編程
D. 方便程序的測試
Spring對Junit4支持,可以通過注解方便的測試Spring程序
E. 方便集成各種優秀框架
Spring不排斥各種優秀的開源框架,其內部提供了對各種優秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
F. 降低JavaEE API的使用難度
Spring 對JavaEE開發中非常難用的一些API(JDBC、JavaMail、遠程調用等),都提供了封裝,使這些API應用難度大大降低。
Spring的體系結構

Spring的核心
Spring的核心是控制反轉(IoC)和面向切面(AOP)。
控制反轉(IOC)
IoC理論的背景
我們都知道,在采用面向對象方法設計的軟件系統中,它的底層實現都是由N個對象組成的,所有的對象通過彼此的合作,最終實現系統的業務邏輯。

如果我們打開機械式手表的后蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針旋轉,從而在表盤上產生正確的時間。圖1中描述的就是 這樣的一個齒輪組,它擁有多個獨立的齒輪,這些齒輪相互嚙合在一起,協同工作,共同完成某項任務。我們可以看到,在這樣的齒輪組中,如果有一個齒輪出了問 題,就可能會影響到整個齒輪組的正常運轉。
齒輪組中齒輪之間的嚙合關系,與軟件系統中對象之間的耦合關系非常相似。對象之間的耦合關系是無法避免的,也是必要的,這是協同工作的基礎。現在,伴隨着工業級應用的規模越來越龐大,對象之間的依賴關系也越來越復雜,經常會出現對象之間的多重依賴性關系,因此,架構師和設計師對於系統的分析和設計,將面臨 更大的挑戰。對象之間耦合度過高的系統,必然會出現牽一發而動全身的情形。

耦合關系不僅會出現在對象與對象之間,也會出現在軟件系統的各模塊之間,以及軟件系統和硬件系統之間。如何降低系統之間、模塊之間和對象之間的耦合度,是軟件工程永遠追求的目標之一。為了解決對象之間的耦合度過高的問題,軟件專家Michael Mattson提出了IOC理論,用來實現對象之間的“解耦”,目前這個理論已經被成功地應用到實踐當中,很多的J2EE項目均采用了IOC框架產品Spring。
什么是控制反轉(IoC)
IOC是Inversion of Control的縮寫,多數書籍翻譯成“控制反轉”,還有些書籍翻譯成為“控制反向”或者“控制倒置”。
1996年,Michael Mattson在一篇有關探討面向對象框架的文章中,首先提出了IOC 這個概念。對於面向對象設計及編程的基本思想,前面我們已經講了很多了,不再贅述,簡單來說就是把復雜系統分解成相互合作的對象,這些對象類通過封裝以后,內部實現對外部是透明的,從而降低了解決問題的復雜度,而且可以靈活地被重用和擴展。IOC理論提出的觀點大體是這樣的:借助於“第三方”實現具有依 賴關系的對象之間的解耦,如下圖:

大家看到了吧,由於引進了中間位置的“第三方”,也就是IOC容器,使得A、B、C、D這4個對象沒有了耦合關系,齒輪之間的傳動全部依靠“第三方”了, 全部對象的控制權全部上繳給“第三方”IOC容器,所以,IOC容器成了整個系統的關鍵核心,它起到了一種類似“粘合劑”的作用,把系統中的所有對象粘合 在一起發揮作用,如果沒有這個“粘合劑”,對象與對象之間會彼此失去聯系,這就是有人把IOC容器比喻成“粘合劑”的由來。
我們再來做個試驗:把上圖中間的IOC容器拿掉,然后再來看看這套系統:

我們現在看到的畫面,就是我們要實現整個系統所需要完成的全部內容。這時候,A、B、C、D這4個對象之間已經沒有了耦合關系,彼此毫無聯系,這樣的話, 當你在實現A的時候,根本無須再去考慮B、C和D了,對象之間的依賴關系已經降低到了最低程度。所以,如果真能實現IOC容器,對於系統開發而言,這將是 一件多么美好的事情,參與開發的每一成員只要實現自己的類就可以了,跟別人沒有任何關系!
Ioc—Inversion of Control,即“控制反轉”,不是什么技術,而是一種設計思想。在Java開發中,Ioc意味着將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。如何理解好Ioc呢?理解好Ioc的關鍵是要明確“誰控制誰,控制什么,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”,那我們來深入分析一下:
●誰控制誰,控制什么:傳統Java SE程序設計,我們直接在對象內部通過new進行創建對象,是程序主動去創建依賴對象;而IoC是有專門一個容器來創建這些對象,即由Ioc容器來控制對 象的創建;誰控制誰?當然是IoC 容器控制了對象;控制什么?那就是主要控制了外部資源獲取(不只是對象包括比如文件等)。
●為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程序是由我們自己在對象中主動控制去直接獲取依賴對象,也就是正轉;而反轉則是由容器來幫忙創建及注入依賴對象;為何是反轉?因為由容器幫我們查找及注入依賴對象,對象只是被動的接受依賴對象,所以是反轉;哪些方面反轉了?依賴對象的獲取被反轉了。
IOC的應用(能做什么)
IoC 不是一種技術,只是一種思想,一個重要的面向對象編程的法則,它能指導我們如何設計出松耦合、更優良的程序。傳統應用程序都是由我們在類內部主動創建依賴對象,從而導致類與類之間高耦合,難於測試;有了IoC容器后,把創建和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,所以對象與對象之間是 松散耦合,這樣也方便測試,利於功能復用,更重要的是使得程序的整個體系結構變得非常靈活。
其實IoC對編程帶來的最大改變不是從代碼上,而是從思想上,發生了“主從換位”的變化。應用程序原本是老大,要獲取什么資源都是主動出擊,但是在IoC/DI思想中,應用程序就變成被動的了,被動的等待IoC容器來創建並注入它所需要的資源了。
IoC很好的體現了面向對象設計法則之一—— 好萊塢法則:“別找我們,我們找你”;即由IoC容器幫對象找相應的依賴對象並注入,而不是由對象主動去找。
DI(依賴注入)
2004年,Martin Fowler探討了同一個問題,既然IOC是控制反轉,那么到底是“哪些方面的控制被反轉了呢?”,經過詳細地分析和論證后,他得出了答案:“獲得依賴對象的過程被反轉了”。控制被反轉之后,獲得依賴對象的過程由自身管理變為了由IOC容器主動注入。於是,他給“控制反轉”取了一個更合適的名字叫做“依賴 注入(Dependency Injection)”。他的這個答案,實際上給出了實現IOC的方法:注入。所謂依賴注入,就是由IOC容器在運行期間,動態地將某種依賴關系注入到對象之中。
所以,依賴注入(DI)和控制反轉(IOC)是從不同的角度的描述的同一件事情,就是指通過引入IOC容器,利用依賴關系注入的方式,實現對象之間的解耦。
我們舉一個生活中的例子,來幫助理解依賴注入的過程。大家對USB接口和USB設備應該都很熟悉吧,USB為我們使用電腦提供了很大的方便,現在有很多的外部設備都支持USB接口。

現在,我們利用電腦主機和USB接口來實現一個任務:從外部USB設備讀取一個文件。
電腦主機讀取文件的時候,它一點也不會關心USB接口上連接的是什么外部設備,而且它確實也無須知道。它的任務就是讀取USB接口,掛接的外部設備只要符 合USB接口標准即可。所以,如果我給電腦主機連接上一個U盤,那么主機就從U盤上讀取文件;如果我給電腦主機連接上一個外置硬盤,那么電腦主機就從外置 硬盤上讀取文件。掛接外部設備的權力由我作主,即控制權歸我,至於USB接口掛接的是什么設備,電腦主機是決定不了,它只能被動的接受。電腦主機需要外部 設備的時候,根本不用它告訴我,我就會主動幫它掛上它想要的外部設備,你看我的服務是多么的到位。這就是我們生活中常見的一個依賴注入的例子。在這個過程 中,我就起到了IOC容器的作用。
通過這個例子,依賴注入的思路已經非常清楚:當電腦主機讀取文件的時候,我就把它所要依賴的外部設備,幫他掛接上。整個外部設備注入的過程和一個被依賴的對象在系統運行時被注入另外一個對象內部的過程完全一樣。
我們把依賴注入應用到軟件系統中,再來描述一下這個過程:
對象A依賴於對象B,當對象 A需要用到對象B的時候,IOC容器就會立即創建一個對象B送給對象A。IOC容器就是一個對象制造工廠,你需要什么,它會給你送去,你直接使用就行了, 而再也不用去關心你所用的東西是如何制成的,也不用關心最后是怎么被銷毀的,這一切全部由IOC容器包辦。
在傳統的實現中,由程序內部代碼來控制組件之間的關系。我們經常使用new關鍵字來實現兩個組件之間關系的組合,這種實現方式會造成組件之間耦合。IOC 很好地解決了該問題,它將實現組件間關系從程序內部提到外部容器,也就是說由容器在運行期將組件間的某種依賴關系動態注入組件中。
Spring的入門案例
1.創建java項目,導入jar包

2.編寫配置文件
UserDao.java
package dao; public interface UserDao { void addUser(); void deleteUser(); }
UserDaoImpl.java
package dao.impl; import dao.UserDao; public class UserDaoImpl implements UserDao{ @Override public void addUser() { System.out.println("添加用戶"); } @Override public void deleteUser() { System.out.println("刪除用戶"); } }
UserService.java
package service; public interface UserService { void addUser(); void deleteUser(); }
UserServiceImpl.java
package service.impl; import dao.UserDao; import service.UserService; public class UserServiceImpl implements UserService{ UserDao dao; //spring 接口+setter方式 設值注入 public void setDao(UserDao dao) { this.dao = dao; } @Override public void addUser() { dao.addUser(); } @Override public void deleteUser() { dao.deleteUser(); } }
ApplicatitonContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- bean:創建和管理一個對象 id:bean唯一標識(對象名稱) class:類的全限定名稱 --> <bean id="userdao" class="dao.impl.UserDaoImpl"></bean> <!-- 調用無參構造創建對象 property:屬性 name:屬性的名稱,此處為UserServiceImpl.java文件中的屬性dao value:屬性的值(簡單) ref:引用(對象) 指向另一個bean的id,此處為上面bean的id --> <bean id="userservice" class="service.impl.UserServiceImpl"> <property name="dao" ref="userdao"></property> </bean> </beans>
Test.java
package test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.UserService; public class Test { @org.junit.Test public void test() { //加載配置文件獲取spring容器 ApplicationContext context = new ClassPathXmlApplicationContext("ApplicatitonContext.xml"); //從spring容器中獲取userservice對象 UserService service = context.getBean("userservice",UserService.class); service.addUser(); service.deleteUser(); } }
運行結果
二月 01, 2018 8:00:00 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2a33fae0: startup date [Thu Feb 01 20:00:00 CST 2018]; root of context hierarchy 二月 01, 2018 8:00:00 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [ApplicatitonContext.xml] 添加用戶 刪除用戶
