1. 框架概述
1.1 目的
Spring的主要的目的是簡(jiǎn)化java開發(fā):
- 基于POJO的輕量級(jí)和最小侵入性編程蚓再;
- 通過依賴注入和面向接口實(shí)現(xiàn)松耦合拆内;
- 基于切面和慣例進(jìn)行聲明式編程挽牢;
- 通過切面和模板減少樣板式代碼
1.2 核心技術(shù)
Spring中核心的功能由控制反轉(zhuǎn)和切面編程實(shí)現(xiàn)。
1.2.1 控制反轉(zhuǎn)IOC
控制反轉(zhuǎn)(Inversion of Control ,Ioc)
所謂控制反轉(zhuǎn)就是應(yīng)用本身不負(fù)責(zé)依賴對(duì)象的創(chuàng)建及維護(hù),依賴對(duì)象的創(chuàng)建及維護(hù)由外部容器來負(fù)責(zé)喷户。這樣控制權(quán)就由應(yīng)用轉(zhuǎn)移到了外部容器,控制權(quán)的轉(zhuǎn)移就是所謂反轉(zhuǎn)访锻。
依賴注入就是指:在運(yùn)行期間褪尝,有外部容器動(dòng)態(tài)地將依賴對(duì)象注入到組件中(構(gòu)造方法和set方法)
使用IOC的優(yōu)勢(shì)是:其降低組件之間的耦合度,實(shí)現(xiàn)軟件各層之間的解耦.
在Spring中實(shí)現(xiàn)依賴注入有xml, javaconfig和annotation三種方式期犬。
1.2.2 AOP
AOP是面向切面的河哑,它使得業(yè)務(wù)邏輯和非業(yè)務(wù)邏輯分離,允許你把遍布應(yīng)用各處的功能分離出來形成可重用的組件龟虎。
常用到的場(chǎng)景: 安全璃谨,日志,緩存等
面向切面編程往往被定義為促使軟件系統(tǒng)實(shí)現(xiàn)關(guān)注點(diǎn)的分離一項(xiàng)技
術(shù)鲤妥。系統(tǒng)由許多不同的組件組成佳吞,每一個(gè)組件各負(fù)責(zé)一塊特定功能。
除了實(shí)現(xiàn)自身核心的功能之外棉安,這些組件還經(jīng)常承擔(dān)著額外的職責(zé)底扳。
諸如日志、事務(wù)管理和安全這樣的系統(tǒng)服務(wù)經(jīng)常融入到自身具有核心
業(yè)務(wù)邏輯的組件中去贡耽,這些系統(tǒng)服務(wù)通常被稱為橫切關(guān)注點(diǎn)衷模,因?yàn)樗?br>
們會(huì)跨越系統(tǒng)的多個(gè)組件
概念:
通知: 即切面的工作。
Spring切面可以應(yīng)用5種類型的通知:
- 前置通知(Before):在目標(biāo)方法被調(diào)用之前調(diào)用通知功能蒲赂;
- 后置通知(After):在目標(biāo)方法完成之后調(diào)用通知阱冶,此時(shí)不會(huì)關(guān)
心方法的輸出是什么; - 返回通知(After-returning):在目標(biāo)方法成功執(zhí)行之后調(diào)用通
知凳宙; - 異常通知(After-throwing):在目標(biāo)方法拋出異常后調(diào)用通知熙揍;
- 環(huán)繞通知(Around):通知包裹了被通知的方法,在被通知的方
法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為氏涩。
切點(diǎn): 定義了在何處執(zhí)行通知
切面:切面是通知和切點(diǎn)的結(jié)合届囚。通知和切點(diǎn)共同定義了切面的全部內(nèi)容
——它是什么有梆,在何時(shí)和何處完成其功能
織入(Weaving)
織入是把切面應(yīng)用到目標(biāo)對(duì)象并創(chuàng)建新的代理對(duì)象的過程。切面在指
定的連接點(diǎn)被織入到目標(biāo)對(duì)象中意系。在目標(biāo)對(duì)象的生命周期里有多個(gè)點(diǎn)
可以進(jìn)行織入: - 編譯期:切面在目標(biāo)類編譯時(shí)被織入泥耀。這種方式需要特殊的編譯
器。AspectJ的織入編譯器就是以這種方式織入切面的蛔添。 - 類加載期:切面在目標(biāo)類加載到JVM時(shí)被織入痰催。這種方式需要特
殊的類加載器(ClassLoader),它可以在目標(biāo)類被引入應(yīng)用
之前增強(qiáng)該目標(biāo)類的字節(jié)碼迎瞧。AspectJ 5的加載時(shí)織入(load-time
weaving夸溶,LTW)就支持以這種方式織入切面。 - 運(yùn)行期:切面在應(yīng)用運(yùn)行的某個(gè)時(shí)刻被織入凶硅。一般情況下缝裁,在織
入切面時(shí),AOP容器會(huì)為目標(biāo)對(duì)象動(dòng)態(tài)地創(chuàng)建一個(gè)代理對(duì)象足绅。
Spring AOP就是以這種方式織入切面的捷绑。
1.2.2 使用
-
編寫切點(diǎn)
如下: 其展現(xiàn)了一個(gè)切點(diǎn)表達(dá)式,這個(gè)表達(dá)式能夠設(shè)置黨perform方法執(zhí)行時(shí)觸發(fā)通知氢妈。
編寫切面:
實(shí)現(xiàn)切面的通知之后粹污,然后在通知中添加相應(yīng)的切點(diǎn)信息即可實(shí)現(xiàn)切面的定義。
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance() {}
@Before("performance()")
public void silenceCellPhones() {
System.out.println("Silencing cell phones");
}
1.3 容器
之前的servlet中容器負(fù)責(zé)servlet的生成首量,調(diào)用和銷毀的過程壮吩。在基于Spring的應(yīng)用中,你的應(yīng)用對(duì)象生存于Spring容器(container)中蕾总,Spring容器負(fù)責(zé)創(chuàng)建對(duì)象粥航,裝配它們,配置它們并管理它們的整個(gè)生命周期生百,從生存到死亡(在這里递雀,可能就是new到finalize())。
Spring容器并不是只有一個(gè)蚀浆。Spring自帶了多個(gè)容器實(shí)現(xiàn)缀程,可以歸為
兩種不同的類型。
- bean工廠(由org.springframework. beans.factory.eanFactory接口定義)是最簡(jiǎn)單的容器市俊,提供基本的DI支持杨凑。
- 應(yīng)用上下文(org.springframework.context.ApplicationContext接口定義)基于BeanFactory構(gòu)建,并提供應(yīng)用框架級(jí)別的服務(wù)摆昧,例如從屬性文件解析文本信息以及發(fā)布應(yīng)用事件給感興趣的事件監(jiān)聽者撩满。
spring提供的應(yīng)用上下文(最可能遇到的):
- AnnotationConfigApplicationContext:從一個(gè)或多個(gè)基于Java的配置類中加載Spring應(yīng)用上下文。
- AnnotationConfigWebApplicationContext:從一個(gè)或多個(gè)基于Java的配置類中加載Spring Web應(yīng)用上下文。
- ClassPathXmlApplicationContext:從類路徑下的一個(gè)或
多個(gè)XML配置文件中加載上下文定義伺帘,把應(yīng)用上下文的定義文件
作為類資源昭躺。 - FileSystemXmlapplicationcontext:從文件系統(tǒng)下的一個(gè)或多個(gè)XML配置文件中加載上下文定義。
- XmlWebApplicationContext:從Web應(yīng)用下的一個(gè)或多個(gè)XML配置文件中加載上下文定義伪嫁。
1.4 整體
Spring框架整體包括了核心容器部分领炫,AOP模塊部分,數(shù)據(jù)集成與訪問张咳,web與遠(yuǎn)程調(diào)用帝洪。
如圖所示:
2. Spring web
在先前的servlet的課程中,代碼出現(xiàn)的問題:
- 不管servlet還是jsp都將java代碼和視圖代碼在不同程度上耦合在一起了脚猾。
- 不能很好的與RESTful API 進(jìn)行結(jié)合葱峡。例如請(qǐng)求地址為:user/{userId}
Spring MVC
Spring MVC 是spring相關(guān)的web框架項(xiàng)目。其整體的工作流程和機(jī)制可以用下圖表示:
DispatcherServlet是Spring MVC的核心龙助,其將請(qǐng)求轉(zhuǎn)發(fā)給合適的控制器族沃。
對(duì)于DispatcherServlet的配置和普通的servlet的配置相同,只不過此時(shí)DispatcherServlet是由spring中實(shí)現(xiàn)好的泌参。
編寫控制器
控制器邏輯上屬于控制處理業(yè)務(wù)邏輯部分,在Spring中以bean的形式出現(xiàn)常空。所以可以使用@Controller注解來標(biāo)注該控制器沽一。
@Controller
public class HomeController {
@RequestMapping(value="/", method=GET)
public String home() {
return "home";
}
}
注意點(diǎn):
- RequestMapping中的value定義了該控制其可以處理的url地址,復(fù)雜的可以用正則表達(dá)式書寫漓糙。method表示可以處理的請(qǐng)求必須滿足的方法铣缠。 其他屬性可以參考
- RequestMapping可以定義在類級(jí)別
- 函數(shù)的參數(shù)可以是下面的任何一種:
- 函數(shù)的返回值可以是下面的任何一種。
- void
- string: view名稱
- HttpEntity
- View
- Map
- Model
- ModelAndView
ViewResolver
spring框架中ViewResolver負(fù)責(zé)視圖的解析工作昆禽,ViewResolver的整體的框架如下:(注:實(shí)現(xiàn)的ViewResolver未標(biāo)注完)
不同的視圖解析器區(qū)別主要在于:面向的視圖資源不同蝗蛙。
- InternalResourceViewResolver : 將視圖解析為Web應(yīng)用的內(nèi)部資源(一般為
JSP) - FreeMarkerViewResolver : 將視圖解析為FreeMarker模板
- ContentNegotiatingViewResolver: 通過考慮客戶端需要的內(nèi)容類型來解析視圖,委托給另外一個(gè)能夠產(chǎn)生對(duì)應(yīng)內(nèi)容類型的視圖解析器.
使用視圖解析器時(shí)需要對(duì)其進(jìn)行配置醉鳖,如下:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
對(duì)于home視圖將被解析為:/WEB-INF/jsp/home.jsp
參考: