spring 的優勢?
1.下降了組件之間的耦合性 ,實現了軟件各層之間的解耦
2.可使用容易提供的衆多服務,如事務管理,消息服務等
3.容器提供單例模式支持
4.容器提供了AOP技術,利用它很容易實現如權限攔截,運行期監控等功能
5.容器提供了衆多的輔助類,能加快應用的開發
6.spring對於主流的應用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring屬於低侵入式設計,代碼的污染極低
8.獨立於各類應用服務器
9.spring的DI機制下降了業務對象替換的複雜性
10.Spring的高度開放性,並不強制應用徹底依賴於Spring,開發者能夠自由選擇spring的部分或所有java
什麼是DI機制?
依賴注入(Dependecy Injection)和控制反轉(Inversion of Control)是同一個概念,具體的講:當某個角色
須要另一個角色協助的時候,在傳統的程序設計過程當中,一般由調用者來建立被調用者的實例。但在spring中
建立被調用者的工做再也不由調用者來完成,所以稱爲控制反轉。建立被調用者的工做由spring來完成,而後注入調用者
所以也稱爲依賴注入。
spring以動態靈活的方式來管理對象 , 注入的兩種方式,設置注入和構造注入。
設置注入的優勢:直觀,天然
構造注入的優勢:能夠在構造器中決定依賴關係的順序。
什麼是AOP?
面向切面編程(AOP)完善spring的依賴注入(DI),面向切面編程在spring中主要表現爲兩個方面
1.面向切面編程提供聲明式事務管理
2.spring支持用戶自定義的切面
面向切面編程(aop)是對面向對象編程(oop)的補充,
面向對象編程將程序分解成各個層次的對象,面向切面編程將程序運行過程分解成各個切面。
AOP從程序運行角度考慮程序的結構,提取業務處理過程的切面,oop是靜態的抽象,aop是動態的抽象,
是對應用執行過程當中的步驟進行抽象,,從而得到步驟之間的邏輯劃分。
aop框架具備的兩個特徵:
1.各個步驟之間的良好隔離性
2.源代碼無關性 spring
本文主要討論Spring聲明式事務中使用註解@Transactional的方式、原理及注意事項,主要包括如下內容:數據庫
1 |
<beans xmlns="http://www.springframework.org/schema/beans" |
<!-- 事務管理器配置,單數據源事務 --> <bean id="pkgouTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="pkGouDataSource" /> </bean> <!-- 使用annotation定義事務 --> <tx:annotation-driven transaction-manager="pkgouTransactionManager" />
1> 事務註解方式: @Transactionalexpress
2> 事務傳播行爲介紹:編程
事務傳播行爲 | 說明 |
---|---|
@Transactional(propagation=Propagation.REQUIRED) | 若是有事務, 那麼加入事務, 沒有的話新建一個(默認狀況) |
@Transactional(propagation=Propagation.NOT_SUPPORTED) | 容器不爲這個方法開啓事務 |
@Transactional(propagation=Propagation.REQUIRES_NEW) | 不論是否存在事務,都建立一個新的事務,原來的掛起,新的執行完畢,繼續執行老的事務 |
@Transactional(propagation=Propagation.MANDATORY) | 必須在一個已有的事務中執行,不然拋出異常 |
@Transactional(propagation=Propagation.NEVER) | 必須在一個沒有的事務中執行,不然拋出異常(與Propagation.MANDATORY相反) |
@Transactional(propagation=Propagation.SUPPORTS) | 若是其餘bean調用這個方法,在其餘bean中聲明事務,那就用事務。若是其餘bean沒有聲明事務,那就不用事務 |
3> 事務超時設置:
@Transactional(timeout=30) //默認是30秒服務器
4> 事務隔離級別:mvc
事務隔離級別 | 說明 |
---|---|
@Transactional(isolation = Isolation.READ_UNCOMMITTED) | 讀取未提交數據(會出現髒讀, 不可重複讀),基本不使用 |
@Transactional(isolation = Isolation.READ_COMMITTED)(SQLSERVER默認) | 讀取已提交數據(會出現不可重複讀和幻讀) |
@Transactional(isolation = Isolation.REPEATABLE_READ) | 可重複讀(會出現幻讀) |
@Transactional(isolation = Isolation.SERIALIZABLE) | 串行化 |
@Transactional的屬性:框架
默認狀況下,數據庫處於自動提交模式。每一條語句處於一個單獨的事務中,在這條語句執行完畢時,若是執行成功則隱式的提交事務,若是執行失敗則隱式的回滾事務。
事務管理,是一組相關的操做處於一個事務之中,所以必須關閉數據庫的自動提交模式。這點,Spring會在org/springframework/jdbc/datasource/DataSourceTransactionManager.java中將底層鏈接的自動提交特性設置爲false。oop
1 |
// switch to manual commit if necessary。 this is very expensive in some jdbc drivers, |
Spring事務管理器回滾一個事務的推薦方法是在當前事務的上下文內拋出異常。Spring事務管理器會捕捉任何未處理的異常,而後依據規則決定是否回滾拋出異常的事務。
默認配置下,Spring只有在拋出的異常爲運行時unchecked異常時纔回滾該事務,也就是拋出的異常爲RuntimeException的子類(Errors也會致使事務回滾)。而拋出checked異常則不會致使事務回滾。
Spring也支持明確的配置在拋出哪些異常時回滾事務,包括checked異常。也能夠明肯定義哪些異常拋出時不回滾事務。
還能夠編程性的經過setRollbackOnly()方法來指示一個事務必須回滾,在調用完setRollbackOnly()後你所能執行的惟一操做就是回滾。post
在上一篇文章中,咱們使用了聲明式事務來配置事務,使事務配置從service邏輯處理中解耦出來。但它還存在一些缺點:
1. 咱們只針對方法名的特定進行攔截,但沒法利用方法簽名的其它信息定位,如修飾符、返回值、方法入參、異常類型等。若是咱們須要爲同名不一樣參的同載方法配置不一樣事務就會出問題了。
2. 事務屬性的配置串雖然能包含較多信息,但配置較易出錯。
針對這些問題,咱們能夠基於Schema,引入tx和aop的命名空間來改進咱們的配置:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- 配置事務屬性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRES_NEW" /> <tx:method name="update*" propagation="REQUIRES_NEW" /> <tx:method name="delete*" propagation="REQUIRES_NEW" /> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 配置事務切入點,以及把事務切入點和事務屬性關聯起來 --> <aop:config proxy-target-class="true"> <aop:pointcut expression="execution(* com.yc.service.*.*(..))" id="ServicePointcut" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="ServicePointcut" /> </aop:config>
這裏須要特別注意的是,咱們須要在標籤中將proxy-target-class配置成true,不然會出現和上一篇文章相同的錯誤:咱們定義的類沒法轉換成代理類
這裏咱們經過來配置咱們的事務加強屬性。在標籤中,常見屬性及其說明以下,其中,除了name屬性是必選外,其餘都是可選的:
屬性 | 說明 | 默認 | 容許值 |
---|---|---|---|
name | 匹配方法名 | 必須聲明,至少爲* | 可以使用*通配符 |
propagation | 事務傳播行爲 | REQUIRED | REQUIRED,SUPPORTS和MANDATORY和REQUIRES_NEW和NOT_SUPPORTED和NEVER和NESTED |
read-only | 設置當前事務是否只讀 | false | true,false |
isolation | 事務隔離級別 | DEFAULT | READ_UNCOMMITTED和READ_COMMITTED和REPEATABLE_READ和SERIALIZABLE |
timeout | 設置事務的超時時間 | -1 | 默認由頂層事務系統決定 |
rollback-for | 內容爲異常名,表示當拋出這些異常時事務回滾,能夠用逗號分隔配置多個 | 無默認值 | 可使用異常名稱的片斷進行匹配如ception等 |
no-rollback-for | 內容爲異常名,表示當拋出這些異常時繼續提交事務,能夠用逗號分隔配置多個 | 無默認值 | 可使用異常名稱的片斷進行匹配如ception等。 |