前言
spring是一個(gè)開(kāi)源框架,spring是于2003 年興起的一個(gè)輕量級(jí)的java 開(kāi)發(fā)框架,由rod johnson 在其著作expert one-on-one j2ee development and design中闡述的部分理念和原型衍生而來(lái)。它是為了解決企業(yè)應(yīng)用開(kāi)發(fā)的復(fù)雜性而創(chuàng)建的。spring使用基本的javabean來(lái)完成以前只可能由ejb完成的事情。然而,spring的用途不僅限于服務(wù)器端的開(kāi)發(fā)。從簡(jiǎn)單性、可測(cè)試性和松耦合的角度而言,任何java應(yīng)用都可以從spring中受益。 簡(jiǎn)單來(lái)說(shuō),spring是一個(gè)輕量級(jí)的控制反轉(zhuǎn)(ioc)和面向切面(aop)的容器框架。
這篇文章主要講 spring 中的幾個(gè)點(diǎn),spring 中的 ioc,aop,下一篇說(shuō)說(shuō) spring 中的事務(wù)操作,注解和 xml 配置。
spring 簡(jiǎn)介
spring 是一個(gè)開(kāi)源的輕量級(jí)的企業(yè)級(jí)框架,其核心是反轉(zhuǎn)控制 (ioc) 和面向切面 (aop) 的容器框架。我們可以把 spring 看成是對(duì)象的容器,容器中可以包含很多對(duì)象,所以 spring 有很多強(qiáng)大的功能。
一句話,spring 是項(xiàng)目中對(duì)象的管家,負(fù)責(zé)管理項(xiàng)目中用到的所有對(duì)象。所以在項(xiàng)目三層架構(gòu)中,spring 不屬于某一特定層。
spring 的 hello world
想要構(gòu)建一個(gè) spring 的入門(mén)程序,我們需要導(dǎo)入 4 個(gè)核心包和 2 個(gè)輔助包,創(chuàng)建一個(gè)實(shí)體類(lèi),最主要的是編寫(xiě)核心配置文件,applicationcontext.xml 放在 src 下。最后寫(xiě)一個(gè)測(cè)試類(lèi)即可。此時(shí)在測(cè)試類(lèi)中我們不需要在使用 new 關(guān)鍵字去創(chuàng)建對(duì)象了。這也正是 spring 的作用所在,會(huì)自動(dòng)給我創(chuàng)建對(duì)象。
上圖展示的就是最基本的演示,也是很容易就理解了,配置文件中配置了 user 對(duì)象,我們通過(guò)加載配置文件來(lái)獲取對(duì)象從而避免了使用 new 來(lái)創(chuàng)建。
什么是 ioc
到這里我們就可以解釋一下 spring 中的核心概念之一的 ioc,即 inverse of control ,翻譯過(guò)來(lái)就是反轉(zhuǎn)控制。想想我們以前想要一個(gè)對(duì)象就會(huì)主動(dòng)的 new ?,F(xiàn)在 spring 會(huì)幫我們創(chuàng)建對(duì)象,不需要手工 new(但是要記得配置呀)反轉(zhuǎn)說(shuō)的就是創(chuàng)建對(duì)象的方式反轉(zhuǎn)了,以前是我們自己創(chuàng)建對(duì)象,現(xiàn)在由 spring 為我們創(chuàng)建。
控制又是指什么呢?一個(gè)對(duì)象要有屬性值吧,還有可能存在其它的對(duì)象,控制說(shuō)的就是這些屬性和引用不需要自己寫(xiě)了,由 spring 來(lái)為我們自動(dòng)創(chuàng)建(其實(shí)還是我們自己配置的~)。
總結(jié)下來(lái)就是 spring 可以自動(dòng)的為我們創(chuàng)建對(duì)象,并注入依賴。而反轉(zhuǎn)控制說(shuō)的就是以前我們自己創(chuàng)建對(duì)象和依賴,現(xiàn)在由程序?yàn)槲覀儎?chuàng)建。
spring 創(chuàng)建對(duì)象的方式
那 spring 又是如何為我們創(chuàng)建的呢?我們知道對(duì)象的創(chuàng)建必須要經(jīng)過(guò)構(gòu)造器,從上面的例子中看到,我們只配置了一個(gè)<bean>標(biāo)簽,其實(shí)這就是將空參構(gòu)造器使用配置文件給表示出來(lái)罷了。spring 中創(chuàng)建對(duì)象也就是這么簡(jiǎn)單,當(dāng)然配置可以更復(fù)雜些,后面再說(shuō),但目前我們可以知道,spring 創(chuàng)建對(duì)象的就是通過(guò)配置 bean 標(biāo)簽,調(diào)用構(gòu)造器來(lái)實(shí)現(xiàn)的。如何調(diào)用構(gòu)造器的,那肯定是反射搞的鬼。
藏在 ioc 背后的 di
di,dependency injection,即依賴注入。ioc 還體現(xiàn)在自動(dòng)注入依賴,依賴注入這詞聽(tīng)起來(lái)不太明白,簡(jiǎn)單的理解為綁定數(shù)據(jù),這是一種具體的技術(shù),ioc 是思想,di 是技術(shù)實(shí)現(xiàn)。對(duì)象之中需要其它的對(duì)象,類(lèi)如 service 層中需要 dao 層對(duì)象,我們不需要在 service 中手動(dòng) new 了,只需要配置一下即可。
常用的注入方式有兩種,set 方法注入和構(gòu)造方法注入。而每一種注入方式中又有注入基本數(shù)據(jù)類(lèi)型和引用數(shù)據(jù)類(lèi)型之分。下面就看看如何配置。
set 方法注入
通過(guò) property 標(biāo)簽來(lái)配置屬性,基本數(shù)據(jù)類(lèi)型使用 value 屬性即可,若是引用類(lèi)型則使用 ref 。注意,user 對(duì)象中要有 car 引用并且提供其 set 方法。
構(gòu)造方法注入
這個(gè)配置看一眼就基本理解了,非常簡(jiǎn)單,說(shuō)個(gè)小細(xì)節(jié),對(duì)象的創(chuàng)建需要執(zhí)行構(gòu)造器,我們?cè)诔跏蓟瘜?duì)象的時(shí)候會(huì)使用反射通過(guò)全類(lèi)名得到對(duì)象,而這時(shí)就需要一個(gè)空參的構(gòu)造器,我們不提供構(gòu)造器的情況下,程序會(huì)自動(dòng)為我們提供一個(gè)空參構(gòu)造器,但是一旦重寫(xiě)構(gòu)造器,我們就需要提供空參構(gòu)造器,不然就報(bào)錯(cuò)。
雖然還有其它屬性注入的方式,比方說(shuō) p 名稱空間注入,spel 注入,但是這些都不重要!最常用的就一個(gè)那就是 set 方法注入。抓住重點(diǎn),簡(jiǎn)單省時(shí)。
總結(jié)一下,以上主要說(shuō)了什么是 spring,如何搭建入門(mén)項(xiàng)目,解釋了 ioc 思想,以及站在 ioc 背后的技術(shù) di,我們使用 set 方式注入基本數(shù)據(jù)類(lèi)型和引用數(shù)據(jù)類(lèi)型,當(dāng)然,這些東西都構(gòu)建在反射之上。
aop 介紹
aop 是我們經(jīng)常聽(tīng)到的概念,然而聽(tīng)的太多我們卻忘記了最初的定義,全稱 aspect oriented programming 翻譯過(guò)來(lái)就是面向切面編程。首先,要搞清楚這是一種思想,spring 的核心思想就有 aop 。
嘗試?yán)斫庖幌?aop 的思想,簡(jiǎn)單來(lái)說(shuō)就是“縱向重復(fù),橫向抽取”這很抽象,舉幾個(gè)例子,filter 的思想,過(guò)濾器在解決亂碼的時(shí)候不需要我們?cè)诿恳粋€(gè)類(lèi)中都寫(xiě)處理亂碼的代碼。而是直接由 fliter 來(lái)統(tǒng)一處理。還有攔截器的思想,我們?cè)?action 中需要對(duì)參數(shù)進(jìn)行校驗(yàn)、封裝,而攔截器又是統(tǒng)一對(duì)參數(shù)進(jìn)行校驗(yàn)、封裝。
不管是 fliter 還是攔截器,都是面向切面編程思想的具體應(yīng)用。而我們今天說(shuō)的 spring 中的 aop 又是如何體現(xiàn)呢?
動(dòng)態(tài)代理和 cglib 代理
那就是通過(guò)代理,spring 中通過(guò)代理達(dá)到統(tǒng)一增強(qiáng)代理對(duì)象的目的,而不需要對(duì)類(lèi)中的方法一個(gè)一個(gè)增強(qiáng)。我們以前接觸過(guò)動(dòng)態(tài)代理,知道在動(dòng)態(tài)代理中我們的代理對(duì)象和被代理對(duì)象需要實(shí)現(xiàn)同一個(gè)接口,在 spring 中無(wú)法保證每個(gè)需要增強(qiáng)的類(lèi)都實(shí)現(xiàn)接口,所以就需要引用另外一種代理技術(shù) cglib 代理。
總結(jié)一下就是 spring 中通過(guò)代理來(lái)體現(xiàn) aop 的思想,而代理的實(shí)現(xiàn)又分為動(dòng)態(tài)代理和 cglib 代理。動(dòng)態(tài)代理要求代理類(lèi)和被代理類(lèi)實(shí)現(xiàn)同一個(gè)接口。而 cglib 是繼承代理,代理對(duì)象只需繼承被代理對(duì)象即可實(shí)現(xiàn)。在 spring 中優(yōu)先使用動(dòng)態(tài)代理。
兩種代理方式有不同的測(cè)試代碼,這里我不再展示,當(dāng)我敲代碼的時(shí)候我突然想到來(lái)上海第一次面試的時(shí)候,面試官就讓我實(shí)現(xiàn)一下 spring 中的 aop,現(xiàn)在終于想通了,就是讓我寫(xiě)一下兩種代理方法的實(shí)現(xiàn)呀??上?,當(dāng)時(shí)一臉懵逼……
spring 中與 aop 相關(guān)名詞
連接點(diǎn)(joinpoint): 在目標(biāo)對(duì)象中,所有可以增強(qiáng)的方法。
切入點(diǎn)(pointcut): 在目標(biāo)對(duì)象中,已經(jīng)增強(qiáng)的方法。
增強(qiáng)/通知(advice): 增強(qiáng)的代碼。
目標(biāo)對(duì)象(target): 被代理對(duì)象。
織入(weaving): 將通知應(yīng)用到到連接點(diǎn)。
代理(proxy): 將通知織入到目標(biāo)對(duì)象形成代理對(duì)象。
切面(aspect): 切入點(diǎn)+通知。
下面通過(guò)代碼展示一下 spring 中 aop 的展示,順帶看看與這幾個(gè)名詞的對(duì)象關(guān)系。
上面的整個(gè)過(guò)程就是 spring 中 aop 的體現(xiàn),將通知織入到目標(biāo)對(duì)象中形成代理的這么一個(gè)過(guò)程。我們?yōu)榱诉@個(gè)需要準(zhǔn)備目標(biāo)對(duì)象,通知對(duì)象,還要學(xué)會(huì)如何配置切點(diǎn)和切面。
上面只是為了測(cè)試一下能否正確的生成代理對(duì)象,而在 spring 中真正應(yīng)用 aop 的是對(duì)事務(wù)的處理。spring aop 實(shí)質(zhì)就是幫我們生成代理對(duì)象,而這個(gè)代理對(duì)象包含了對(duì)事務(wù)的處理。我們通過(guò)配置即可生成代理對(duì)象,而不需要我們?cè)偈智么a處理事務(wù)。
在 spring 中還提供了使用注解來(lái)配置,注釋的出現(xiàn)就是為了替換配置文件,然而注釋使用的不多。
總結(jié)一下,ioc 和 aop 都是 spring 中的核心概念,ioc 體現(xiàn)在 spring 會(huì)為我們自動(dòng)創(chuàng)建對(duì)象,由以前的手動(dòng) new 對(duì)象,到現(xiàn)在 spring 統(tǒng)一管理。
我想到一個(gè)例子來(lái)說(shuō)明一下 aop,高速路上的收費(fèi)站就是一個(gè)切面,spring 的 ioc 就是一個(gè)發(fā)車(chē)站,負(fù)責(zé)維護(hù)汽車(chē)對(duì)象和依賴對(duì)象汽車(chē)上的人,車(chē)就是目標(biāo)對(duì)象,而我們要生成的代理對(duì)象就是通過(guò)收費(fèi)站的汽車(chē)。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。
原文鏈接:https://www.cnblogs.com/YJK923/p/10187076.html