控制反轉(zhuǎn): 把創(chuàng)建對(duì)象的權(quán)利交給框架,在使用過(guò)程中直接去得到這個(gè)對(duì)象;它包括依賴注入(Dependency Injection或粮,簡(jiǎn)稱DI)和依賴查找(Dependency Lookup);
Spring 概況
Spring 是一個(gè)開(kāi)源框架朵锣,為了解決企業(yè)應(yīng)用開(kāi)發(fā)的復(fù)雜性而創(chuàng)建的谬盐,但現(xiàn)在已經(jīng)不止應(yīng)用于企業(yè)應(yīng)用。
-
是一個(gè)輕量級(jí)的控制反轉(zhuǎn)(IOC)和面向切面(AOP)編程的容器框架
- 從大小和開(kāi)銷兩方面而言 Spring 都是輕量的
- 通過(guò)控制反轉(zhuǎn)(IOC)的技術(shù)達(dá)到松耦合的目的
- 提供了面向切面(AOP)編程的豐富的支持诚些,允許通過(guò)分離應(yīng)用的業(yè)務(wù)邏輯與系統(tǒng)級(jí)服務(wù)進(jìn)行內(nèi)聚性的開(kāi)發(fā)
- 包含并管理應(yīng)用對(duì)象的配置和生命周期设褐,這個(gè)意義上是一種容器 【它會(huì)管理由 Spring 它自己創(chuàng)建的對(duì)象,管理對(duì)象配置的信息以及這個(gè)對(duì)象的生命周期泣刹,也就是這個(gè)對(duì)象從創(chuàng)建到銷毀都是由 Spring 自己來(lái)控制的】
- 將簡(jiǎn)單的組件配置助析、組合成為復(fù)雜的應(yīng)用,這個(gè)意義上是框架
Spring 作用
- 容器
- 提供了對(duì)多種技術(shù)的支持和集成
- JMS
- MQ支持
- UnitTest
- ...
- AOP(事務(wù)管理椅您、日志等)
- 提供了眾多方便應(yīng)用的輔助類(JDBC Templatede等)
- 對(duì)主流應(yīng)用框架(Hibernate等)提供了良好的支持
Spring 適用范圍
- 構(gòu)建企業(yè)應(yīng)用(SpringMVC + Spring + Hibernate/ibatis外冀、myBatis)
- 單獨(dú)使用Bean容器(Bean 管理)
- 單獨(dú)使用AOP進(jìn)行切面的處理
- 其他的 Spring 功能,如:對(duì)消息的支持等
- 在互聯(lián)網(wǎng)中的應(yīng)用...
Spring-IOC 控制反轉(zhuǎn)
接口及面向接口編程
-
接口:
- 用于溝通的中介物的抽象化【對(duì)外調(diào)用說(shuō)明掀泳、規(guī)范】
- 實(shí)體把自己提供給外界的一種抽象化說(shuō)明雪隧,用以由內(nèi)部操作分離出外部溝通方法,使其能被修改內(nèi)部而不影響外界其他實(shí)體與其交互的方式【接口是對(duì)外的一種說(shuō)明员舵,說(shuō)明了我會(huì)提供哪些功能脑沿,至于內(nèi)部的實(shí)現(xiàn),對(duì)外是不公開(kāi)的马僻;OC的.h文件也就類似于Java的接口】
- 對(duì)應(yīng) Java 接口即聲明庄拇,聲明了哪些方法是對(duì)外公開(kāi)提供的
- Java 8 中,接口可以擁有方法體
-
面向接口編程:
- 結(jié)構(gòu)設(shè)計(jì)中韭邓,分清層次及調(diào)用關(guān)系措近,每層只向外(上層)
- 好處:接口實(shí)現(xiàn)的變動(dòng)不影響各層級(jí)間的調(diào)用,這一點(diǎn)在向外或企業(yè)內(nèi)部提供公共服務(wù)中尤為重要【穩(wěn)定性】
- “面向接口編程”中的“接口”是用于隱藏具體實(shí)現(xiàn)和實(shí)現(xiàn)多態(tài)性的組件
啥是IOC
IOC: 控制反轉(zhuǎn)女淑,控制權(quán)的轉(zhuǎn)移瞭郑,應(yīng)用程序本省不負(fù)責(zé)依賴對(duì)象的創(chuàng)建和維護(hù),而是由外部容器負(fù)責(zé)創(chuàng)建和維護(hù)鸭你;當(dāng)我們需要一個(gè)對(duì)象的時(shí)候屈张,不是去 new 一個(gè),而是由外部容器創(chuàng)建袱巨,我們向外部容器去申請(qǐng)一個(gè)或者說(shuō)拿來(lái)一個(gè)使用阁谆。
DI(依賴注入):是控制反轉(zhuǎn)的一種實(shí)現(xiàn)方式 ;由 IOC 容器在運(yùn)行期間瓣窄,動(dòng)態(tài)的將某種依賴關(guān)系注入到對(duì)象之中
目的:創(chuàng)建對(duì)象并且組裝對(duì)象之間的關(guān)系
Spring 的 Bean 配置
- 配置:在 spring-ioc.xml 中通過(guò)<bean id="bean的id" class="javaBean實(shí)現(xiàn)類的全路徑"/>配置映射關(guān)系
- 使用:context.getBean(“配置的Bean的id”)拿到 Bean 對(duì)象笛厦,調(diào)用對(duì)應(yīng)的方法
Bean 的初始化
-
基礎(chǔ):兩個(gè)包
- org.springramework.beans : BeanFactory 提供配置結(jié)構(gòu)和基本功能,加載并初始化Bean
- org.springramework.context : ApplicationContext 保存了 Bean 對(duì)象并在 Spring 中被廣泛使用
-
ApplicationContext 初始化方式:
-
加載本地文件
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("F:/workspace/appcontext.xml);
-
Classpath 相對(duì)路徑
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("classpath:spring-context.xml);
-
Web 應(yīng)用中依賴 servlet 或 listener
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>context</servlet-name> <servlet-class>rg.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
-
Spring 常用注入方式
IOC 容器在加載的時(shí)候會(huì)掃描 xml 文件中 Bean 的相關(guān)配置俺夕,然后對(duì)這些 Bean 進(jìn)行實(shí)例化
Spring 注入:是指在啟動(dòng) Spring 容器加載 Bean 配置的時(shí)候裳凸,完成對(duì)變量的賦值行為【A里面有B贱鄙,初始化A的時(shí)候同時(shí)對(duì)B進(jìn)行賦值】
-
注入方式
- 設(shè)值注入:xml 配置 property 屬性對(duì)應(yīng) Bean 的set方法
- 構(gòu)造注入:xml 配置 constructor-arg 屬性對(duì)應(yīng) Bean 的構(gòu)造方 法
Spring Bean
Bean 的配置項(xiàng)
* Id:在整個(gè) IOC 容器中這個(gè) Bean 的唯一標(biāo)識(shí)
* Class:具體要實(shí)例化的哪一個(gè)類
* Scope:范圍,作用域
* Constructor arguments:構(gòu)造器的參數(shù)
* Properties:屬性
* Autowiring mode:自動(dòng)裝配的模式
* lazy-initilizition mode:懶加載模式
* initilizition/destruction method:初始化和銷毀的方法
以上配置項(xiàng)共同構(gòu)成了 Spring IOC 容器中對(duì)于 Bean 的配置姨谷,使用時(shí)理論上只有 Class 是必須的逗宁,其它的都可以不配置,但是想從 Bean 容器中得到某一個(gè)實(shí)例梦湘,兩種方式:Id 和 Bean 的類型瞎颗,如果根據(jù) Id 獲取,那么 Id 這一項(xiàng)就需要配置捌议,如果是根據(jù)類型來(lái)獲取就只需要獲取 Class 這一項(xiàng)哼拔。
Bean 的作用域 (scope)
- singleton:?jiǎn)卫溉萜髦兄淮嬖谝粋€(gè) Bean 的實(shí)例【Spring bean 默認(rèn)模式】
- prototype:每次請(qǐng)求(每次使用)創(chuàng)建新的實(shí)例瓣颅,destory 方式不生效
web 應(yīng)用相關(guān):
- request:每次 http 請(qǐng)求創(chuàng)建一個(gè)實(shí)例僅在當(dāng)前 request 內(nèi)有效
- sesion:同上倦逐,每次 http 請(qǐng)求創(chuàng)建,當(dāng)前 session 內(nèi)有效
- global session:基于 portlet 的 web 中有效(portlet 定義了 global session)宫补,如果是在 web 中檬姥,同session。
Bean 的生命周期
- 定義:Bean xml配置中 定義 id 和 class
- 初始化:當(dāng) IOC 容器 context 啟動(dòng)的時(shí)候加載配置文件中的 Bean 并對(duì)其初始化【可單獨(dú)或全局配置粉怕,三種方式】
- 使用:從 Bean 容器中取出一個(gè) Bean 的實(shí)例健民,然后去調(diào)用它的方法
- 銷毀:Bean 容器停止的時(shí)候銷毀由當(dāng)前這個(gè) Bean 容器創(chuàng)建的所有的 Bean 的實(shí)例
Bean 的自動(dòng)裝配
- NO: 不做任何操作【默認(rèn)】
- byName:根據(jù)屬性名字自動(dòng)裝配。檢查容器并根據(jù)名字查找與屬性完全一致的 bean贫贝,并將其與屬性自動(dòng)裝配秉犹。
default-autowire=“byName”、依賴別的 Bean 的 Bean 中聲明 set 方法 屬性名字跟配置文件中的配置的id一樣平酿。 - byType:如果容器中存在一個(gè)與指定屬性類型相同的bean凤优,那么將與該屬性自動(dòng)裝配悦陋,如果存在多個(gè)該類型的bean蜈彼,那么拋出異常,并指出不能使用 byType 類型進(jìn)行自動(dòng)裝配俺驶;如果未找到相匹配的bean幸逆,那么將不做任何操作【跟上面一樣 只不過(guò)根據(jù) Bean 的類型來(lái)匹配,跟 配置文件里的 Bean 的id無(wú)關(guān)】
- Constructor:與 byType 方式類似暮现,不同之處在于它應(yīng)用于構(gòu)造器參數(shù)还绘,如果容器中沒(méi)有找到于構(gòu)造器參數(shù)類型一致的 Bean 【無(wú)關(guān)id】,拋出異常
Resources&ResourcesLoader
- 針對(duì)資源文件的統(tǒng)一接口【通過(guò) Spring 加載一些資源文件的時(shí)候可以用 Resources 去完成】
Resources
- UrlResources:Url 對(duì)應(yīng)的資源栖袋,根據(jù) Url 地址即可構(gòu)建
- ClassPathResources:獲取類路徑下的資源文件【相對(duì)路徑】
- FileSystemResources:獲取文件系統(tǒng)里面的資源【絕對(duì)路徑】
- ServletContextResources:ServletContext封裝的資源拍顷,用于訪問(wèn)ServletContext環(huán)境下的資源【和web相關(guān)】
- InputStreamResources:針對(duì)于輸入流封裝的資源
- ByteArrayResources:針對(duì)字節(jié)數(shù)組封裝的資源
ResourcesLoader
對(duì) Resources 進(jìn)行加載,在 Spring 容器中塘幅,所有的 ApplicationContext 都實(shí)現(xiàn)了ResourcesLoader 這個(gè)接口昔案,都可以獲取 Resources 的實(shí)例尿贫,
Resources src = ctx.getResources(“資源路徑”); classpath、file:踏揣、http:庆亡、
Bean 的自動(dòng)裝配 - Bean 的定義及作用域的注解實(shí)現(xiàn)
-
Classpath 掃描與組件管理
從 Spring3.0 開(kāi)始,Spring JavaConfig 項(xiàng)目提供了很多特性捞稿,包括使用 java 注解而不是 xml 定義 Bean
@Component 是一個(gè)通用注解又谋,可用于任何 bean
-
@Repository、@Service娱局、@Controller 是 @Component 的子注解彰亥,是更有針對(duì)性的注解。
- @Repository 通常用于注解 DAO 層衰齐,即持久層
- @Service 通常用于注解 Service 類剩愧,即服務(wù)層
- @Controller 通常用于注解 Controller 類,即控制層(MVC)
注解到類上 Spring 可以自動(dòng)檢測(cè)類并注冊(cè) Bean 到 ApplicationContext 上
默認(rèn)情況下娇斩,類被發(fā)現(xiàn)并注冊(cè) bean 的條件是:使用 @Component仁卷、@Repository、@Service犬第、@Controller 注解或使用 @Component 的自定義注解锦积。
@scope:通常情況下自動(dòng)查找的 Spring 組件,其 scope 是 singleton歉嗓,Spring 2.5提供了一個(gè)標(biāo)識(shí)scope的注解 @scope(“xxx”)【使用場(chǎng)景:在每一個(gè)線程中使用一個(gè) bean 的實(shí)例】
@Required:表示受影響的 Bean 屬性必須在配置時(shí)被賦值【不常用】
@AutoWired(自動(dòng)注入):可以理解為一個(gè)傳統(tǒng)的 set 方法丰介,可以用于變量、set方法鉴分、構(gòu)造方法【常用哮幢;默認(rèn)下,如果因找不到合適的 Bean 將會(huì)導(dǎo)致 AutoWired 失敗志珍,拋出異常橙垢;使用前提,配置掃描的范圍
@qualifier:使用在 成員變量伦糯、方法參數(shù)上 作用:縮小范圍
-
基于 Java 容器的注解
- @Bean:類似于XMl配置文件中的<bean/> 柜某,配合@Configuration注解使用
- @ImportResource:引入一個(gè)資源
- @Value(“${屬性名}”):獲取資源文件中的內(nèi)容
- 媽蛋。敛纲。喂击。
AOP 概述
AOP:(Aspect Oriented Programming),面向切面編程淤翔,通過(guò)預(yù)編譯方式 & 運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)翰绊。
主要功能:日志統(tǒng)計(jì),性能統(tǒng)計(jì),安全驗(yàn)證监嗜,事務(wù)處理琳要,異常處理等。
AOP(Aspect Oriented Programming)秤茅,即面向切面編程稚补,可以說(shuō)是OOP(Object Oriented Programming,面向?qū)ο缶幊蹋┑难a(bǔ)充和完善框喳。OOP引入封裝课幕、繼承、多態(tài)等概念來(lái)建立一種對(duì)象層次結(jié)構(gòu)五垮,用于模擬公共行為的一個(gè)集合乍惊。不過(guò)OOP允許開(kāi)發(fā)者定義縱向的關(guān)系,但并不適合定義橫向的關(guān)系放仗,例如日志功能润绎。日志代碼往往橫向地散布在所有對(duì)象層次中,而與它對(duì)應(yīng)的對(duì)象的核心功能毫無(wú)關(guān)系對(duì)于其他類型的代碼诞挨,如安全性莉撇、異常處理和透明的持續(xù)性也都是如此,這種散布在各處的無(wú)關(guān)的代碼被稱為橫切(cross cutting)惶傻,在OOP設(shè)計(jì)中棍郎,它導(dǎo)致了大量代碼的重復(fù),而不利于各個(gè)模塊的重用银室。
AOP技術(shù)恰恰相反涂佃,它利用一種稱為"橫切"的技術(shù),剖解開(kāi)封裝的對(duì)象內(nèi)部蜈敢,并將那些影響了多個(gè)類的公共行為封裝到一個(gè)可重用模塊,并將其命名為"Aspect"抓狭,即切面伯病。所謂"切面",簡(jiǎn)單說(shuō)就是那些與業(yè)務(wù)無(wú)關(guān)辐宾,卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任封裝起來(lái)狱从,便于減少系統(tǒng)的重復(fù)代碼,降低模塊之間的耦合度叠纹,并有利于未來(lái)的可操作性和可維護(hù)性。
使用"橫切"技術(shù)敞葛,AOP把軟件系統(tǒng)分為兩個(gè)部分:核心關(guān)注點(diǎn)和橫切關(guān)注點(diǎn)誉察。業(yè)務(wù)處理的主要流程是核心關(guān)注點(diǎn),與之關(guān)系不大的部分是橫切關(guān)注點(diǎn)惹谐。橫切關(guān)注點(diǎn)的一個(gè)特點(diǎn)是持偏,他們經(jīng)常發(fā)生在核心關(guān)注點(diǎn)的多處驼卖,而各處基本相似,比如權(quán)限認(rèn)證鸿秆、日志酌畜、事物。AOP的作用在于分離系統(tǒng)中的各種關(guān)注點(diǎn)卿叽,將核心關(guān)注點(diǎn)和橫切關(guān)注點(diǎn)分離開(kāi)來(lái)桥胞。
切面是和功能垂直的
AOP實(shí)現(xiàn)方式:
- 預(yù)編譯
- AspectJ
- 運(yùn)行期動(dòng)態(tài)代理(JDK動(dòng)態(tài)代理,CGlib動(dòng)態(tài)代理)
- SpringAOP考婴,JbossAOP
相關(guān)概念:
切面(Aspect):一個(gè)關(guān)注點(diǎn)的模塊化贩虾,這個(gè)關(guān)注點(diǎn)可能會(huì)橫切多個(gè)對(duì)象,多個(gè)對(duì)象執(zhí)行過(guò)程中沥阱,都會(huì)被該切面控制缎罢。
連接點(diǎn)(Joinpoint):程序執(zhí)行過(guò)程中的某個(gè)特定的點(diǎn),【比如一個(gè)類中一個(gè)方法執(zhí)行的開(kāi)始】
-
通知(Advice):在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作【方法執(zhí)行開(kāi)始的時(shí)候額外執(zhí)行的切面的動(dòng)作】
- 前置通知(before advice): < aop:before pointcut-ref=“” method=“” />
- 返回之后的通知(after returning advice): < aop:after-returning pointcut-ref=“” method=“”/>
- 異常后通知(after throwing advice):
- 返回通知(after(finally)advice):< aop:after pointcut-ref=“” method=“”/>【方法結(jié)束前的最后一行代碼】
- 環(huán)繞通知(Around advice):通知方法的第一個(gè)參數(shù)必須是 ProceedingJoinPoint類型考杉;< aop:around>
- 簡(jiǎn)介(introductions):簡(jiǎn)介允許一個(gè)切面聲明一個(gè)實(shí)現(xiàn)指定接口對(duì)象的通知策精,并且提供了一個(gè)接口實(shí)現(xiàn)類來(lái)代表這些對(duì)象
切入點(diǎn)(PointCut):匹配連接點(diǎn)的斷言,在AOP中通知和一個(gè)切入點(diǎn)表達(dá)式關(guān)聯(lián)【如何在切面中匹配一個(gè)具體的連接點(diǎn)】【切入時(shí)機(jī)】【方式賊多崇棠,需要配置】
引入(Introduction):在不修改類代碼的前提下蛮寂,為類添加新的方法和屬性
目標(biāo)對(duì)象(Target Object):被一個(gè)或多個(gè)切面所通知的對(duì)象
AOP代理(AOP Proxy):AOP 框架創(chuàng)建的對(duì)象,用來(lái)實(shí)現(xiàn)切面契約(包括通知方法執(zhí)行等功能)
織入(Weaving):把切面連接到其他的應(yīng)用程序類型或者對(duì)象上易茬,并創(chuàng)建一個(gè)被通知的對(duì)象酬蹋,分為:編譯時(shí)織入,類加載時(shí)織入抽莱,執(zhí)行時(shí)織入【把切面和對(duì)象關(guān)聯(lián)起來(lái)】
Spring AOP 實(shí)現(xiàn):
- 純 java 實(shí)現(xiàn)范抓,無(wú)需特殊的編譯過(guò)程,不需要控制類加載器層次
- 目前只支持方法執(zhí)行連接點(diǎn)(通知 Spring Bean 的方法執(zhí)行)
- 不是為了提供最完整的 AOP 實(shí)現(xiàn)食铐;而是側(cè)重于提供一種 AOP 實(shí)現(xiàn)和 Spring IOC 容器之間的整合匕垫。
- 不會(huì)和 AspectJ(全面綜合解決方案)競(jìng)爭(zhēng),不會(huì)提供全面綜合的解決方案虐呻。
有接口和無(wú)接口Spring AOP 實(shí)現(xiàn)區(qū)別:
- 有接口:默認(rèn)使用標(biāo)準(zhǔn)的 JavaSE 動(dòng)態(tài)代理作為AOP代理象泵,這使得任何接口和任何接口集都可以被代理
- 無(wú)接口:使用CGLib 代理(如果一個(gè)業(yè)務(wù)對(duì)象沒(méi)有實(shí)現(xiàn)任何一個(gè)接口)