首先想說說IoC(Inversionof Control,控制倒轉)。這是spring的核心,貫穿始終。所謂IoC,對於spring框架來講,就是由spring來負責控制對象的生命週期和對象間的關係。這是什麼意思呢,舉個簡單的例子,咱們是如何找女友的?常見的狀況是,咱們處處去看哪裏有長得漂亮身材又好的mm,而後打聽她們的興趣愛 好、qq號、電話號、ip號、iq號………,想辦法認識她們,投其所好送其所要,而後嘿嘿……這個過程是複雜深奧的,咱們必須本身設計和麪對每一個環節。傳 統的程序開發也是如此,在一個對象中,若是要使用另外的對象,就必須獲得它(本身new一個,或者從JNDI中查詢一個),使用完以後還要將對象銷燬(好比Connection等),對象始終會和其餘的接口或類藕合起來。java
那麼IoC是如何作的呢?有點像經過婚介找女友,在我和女友之間引入了一個第三者:婚姻介紹所。婚介管理了不少男男女女的資料,我能夠向婚 介提出一個列表,告訴它我想找個什麼樣的女友,好比長得像李嘉欣,身材像林熙雷,唱歌像周杰倫,速度像卡洛斯,技術像齊達內之類的,而後婚介就會按照我 們的要求,提供一個mm,咱們只須要去和她談戀愛、結婚就好了。簡單明瞭,若是婚介給咱們的人選不符合要求,咱們就會拋出異常。整個過程再也不由我本身控 制,而是有婚介這樣一個相似容器的機構來控制。Spring所倡導的開發方式就是如此,全部的類都會在spring容器中登記,告訴spring你是個什 麼東西,你須要什麼東西,而後spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其餘須要你的東西。全部的類的建立、銷燬都由 spring來控制,也就是說控制對象生存週期的再也不是引用它的對象,而是spring。對於某個具體的對象而言,之前是它控制其餘對象,如今是全部對象 都被spring控制,因此這叫控制反轉。若是你還不明白的話,我決定放棄。web
IoC的一個重點是在系統運行中,動態的向某個對象提供它所須要的其餘對象。這一點是經過DI(Dependency Injection,依賴注入)來實現的。好比對象A須要操做數據庫,之前咱們老是要在A中本身編寫代碼來得到一個Connection對象,有了spring咱們就只須要告訴spring,A中須要一個Connection,至於這個Connection怎麼構造,什麼時候構造,A不須要知道。在系統 運行時,spring會在適當的時候製造一個Connection,而後像打針同樣,注射到A當中,這樣就完成了對各個對象之間關係的控制。A須要依賴 Connection才能正常運行,而這個Connection是由spring注入到A中的,依賴注入的名字就這麼來的。那麼DI是如何實現的呢? Java 1.3以後一個重要特徵是反射(reflection),它容許程序在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性,spring就是經過反射來實現注入的。關於反射的相關資料請查閱java doc。正則表達式
IoC是一個很大的概念,能夠用不一樣的方式來實現。主要的實現形式有兩種:spring
依賴查找:容器提供回調接口和上下文環境給組件。EJB和Apache Avalon都是使用這種方式。數據庫
依賴注入:組件不作定位查詢,只是提供普通的Java方法讓容器去決定依賴關係。容器全權負責組件的裝配,它會把符合依賴關係的對象經過JavaBean屬性或者構造子傳遞給須要的對象。經過JavaBean屬性注射依賴關係的作法稱爲設值方法注入(SetterInjection);將依賴關係做爲構造子參數傳入的作法稱爲構造子注入(ConstructorInjection)。編程
一般,系統由不少組件組成,每一個組件負責一部分功能,然而,這些組件也常常帶有一些除了核心功能以外的附帶功能。系統服務如日誌、事務管理和安全常常融入到一些其餘功能模塊中。這些系統服務一般叫作交叉業務,這是由於它們老是分佈在系統的不少組件中。經過將這些業務分佈在多個組件中,給咱們的代碼引入了雙重複雜性。安全
(1) 實現系統級業務的代碼在多個組件中複製。這意味着若是你要改變這些業務邏輯,你就必須到各個模塊去修改。就算把這些業務抽象成一個獨立模塊,其它模塊只是調用它的一個方法,可是這個方法調用也仍是分佈在不少地方。架構
(2) 組件會由於那些與本身核心業務無關的代碼變得雜亂。一個向地址錄中添加條目的方法應該只關心如何添加地址,而不是關心它是否是安全或支持事務的。框架
此時,咱們該怎麼辦呢?這正是AOP用得着的地方。AOP幫助咱們將這些服務模塊化,並把它們聲明式地應用在須要它們的地方,使得這些組件更加專一於自身業務,徹底不知道其它涉及到的系統服務。模塊化
這裏的概念切面,就是咱們要實現的交叉功能,是應用系統模塊化的一個方面或領域。切面的最多見例子就是日誌記錄。日誌記錄在系統中處處須要用到,利用繼承來重用日誌模塊是不合適的,這樣,就能夠建立一個日誌記錄切面,而且使用AOP在系統中應用。下圖展現了切面應用方式
圖表 1 應用切面
其中,通知Advice是切面的實際實現。鏈接點Joinpoint是應用程序執行過程當中插入切面的地點,這個地點能夠是方法調用,異常拋出,甚至能夠是要修改的字段,切面代碼在這些地方插入到你的應用流程中,添加新的行爲。切入點Pointcut定義了Advice應該應用在那些鏈接點,一般經過指定類名和方法名,或者匹配類名和方法名式樣的正則表達式來指定切入點。
基於AOP,業界存在各類各樣的AOP實現,好比,JBoss AOP、Spring AOP、ASPectJ、AspectWerkz等。各自實現的功能也不同。AOP實現的強弱在很大程度上取決於鏈接點模型。目前,Spring只支持方法級的鏈接點。這和一些其餘AOP框架不同,如AspectJ和JBoss,它們還提供了屬性接入點,這樣能夠防止你建立特別細緻的通知,如對更新對象屬性值進行攔截。然而,因爲Spring關注於提供一個實現J2EE服務的框架,因此方法攔截能夠知足大部分要求,並且Spring的觀點是屬性攔截破壞了封裝,讓Advice觸發在屬性值改變而不是方法調用上無疑是破壞了這個概念。
Spring的AOP框架的關鍵點以下:
(1)Spring實現了AOP聯盟接口。在Spring AOP中,存在以下幾種通知(Advice)類型
Before通知:在目標方法被調用前調用,涉及接口org.springFramework.aop.MethodBeforeAdvice;
After通知:在目標方法被調用後調用,涉及接口爲org.springframework.aop.AfterReturningAdvice;
Throws通知:目標方法拋出異常時調用,涉及接口org.springframework.aop.MethodBeforeAdvice;
Around通知:攔截對目標對象方法調用,涉及接口爲org.aopalliance.intercept.MethodInterceptor。
(2)用Java編寫Spring通知,並在Spring的配置文件中,定義在什麼地方應用通知的切入點。
(3)Spring的運行時通知對象。代理Bean只有在第一次被應用系統須要的時候才被建立。若是你使用的是ApplicationContext,代理對象在BeanFactory載入全部Bean的時候被建立。Spring有兩種代理建立方式。若是目標對象實現了一個或多個接口暴露的方法,Spring將使用JDK的java.lang.reflect.Proxy類建立代理。這個類讓Spring動態產生一個新的類,它實現所需的接口,織入了通知,而且代理對目標對象的全部請求。若是目標對象沒有實現任何接口,Spring使用CGLIB庫生成目標對象的子類。在建立這個子類的時候,Spring將通知織入,而且將對目標對象的調用委託給這個子類。此時,須要將Spring發行包lib/cglib目錄下的JAR文件發佈到應用系統中。
藉助於Spring AOP,Spring IoC可以很方便的使用到很是健壯、靈活的企業級服務,是由於Spring AOP可以提供以下幾方面的優點:
(1)容許開發者使用聲明式企業服務,好比事務服務、安全性服務;EJB開發者都知道,EJB組件可以使用J2EE容器提供的聲明式服務,可是這些服務要藉助於EJB容器,而Spring AOP卻不須要EJB容器,藉助於Spring的事務抽象框架就能夠這些服務。
(2)開發者能夠開發知足業務需求的自定義切面;
(3)開發Spring AOP Advice很方便。由於這些AOP Advice僅是POJO類,藉助於Spring提供的ProxyFactoryBean,可以快速的搭建Spring AOP Advice。
本文詳細闡述了Spring背後的IoC原理和AOP技術,以實際成功項目爲背景,抽取簡短片段,展現了Spring架構J2EE應用系統的原理。SpringIoC藉助於依賴注入機制,減輕了組件之間的依賴關係,同時也大大提升了組件的可移植性,組件獲得了更多的重用機會。藉助於SpringAOP,使得開發者能聲明式、基於元數據訪問企業級服務,AOP合理補充了OOP技術,Spring AOP合理地補充了SpringIoC容器。Spring IoC與SpringAOP組合,使得Spring成爲成功的J2EE架構框架,並能與標準的EJB等標準對抗,EJB再也不是必需品。Spring已經衝入了J2EE的核心,將引領整個J2EE開發、架構的方向。