javascript
Spring的AOP和IOC是什么?使用场景有哪些?Spring事务与数据库事务,传播行为,数据库隔离级别
Spring的AOP和IOC是什么?使用場景有哪些?Spring事務與數據庫事務,傳播行為,數據庫隔離級別
AOP:面向切面編程。
即在一個功能模塊中新增其他功能,比方說你要下樓取個快遞,你同事對你說幫我也取一下唄,你就順道取了。在工作中如果系統中有些包和類中沒有使用AOP,例如日志,事務和異常處理,那么就必須在每個類和方法中去實現它們。 代碼糾纏每個類和方法中都包含日志,事務以及異常處理甚至是業務邏輯。在一個這樣的方法中,很難分清代碼中實際做的是什么處理。AOP 所做的就是將所有散落各處的事務代碼集中到一個事務切面中。
場景
比方說我現在要弄一個日志,記錄某些個接口調用的方法時間。使用Aop我可以在這個接口前插入一段代碼去記錄開始時間,在這個接口后面去插入一段代碼記錄結束時間。
又或者你去訪問數據庫,而你不想管事務(太煩),所以,Spring在你訪問數據庫之前,自動幫你開啟事務,當你訪問數據庫結束之后,自動幫你提交/回滾事務!
異常處理你可以開啟環繞通知,一旦運行接口報錯,環繞通知捕獲異常跳轉異常處理頁面。
動態代理
Spring AOP使用的動態代理,所謂的動態代理就是說AOP框架不會去修改字節碼,而是在內存中臨時為方法生成一個AOP對象,這個AOP對象包含了目標對象的全部方法,并且在特定的切點做了增強處理,并回調原對象的方法。它的動態代理主要有兩種方式,JDK動態代理和CGLIB動態代理。JDK動態代理通過反射來接收被代理的類,并且要求被代理的類必須實現一個接口。JDK動態代理的核心是InvocationHandler接口和Proxy類。如果目標類沒有實現接口,那么Spring AOP會選擇使用CGLIB來動態代理目標類。CGLIB是一個代碼生成的類庫,可以在運行時動態的生成某個類的子類,注意,CGLIB是通過繼承的方式做的動態代理,因此如果某個類被標記為final,那么它是無法使用CGLIB做動態代理的。
IOC:依賴注入或者叫做控制反轉。
正常情況下我們使用一個對象時都是需要new Object()的。而ioc是把需要使用的對象提前創建好,放到spring的容器里面。
所有需要使用的類都會在spring容器中登記,告訴spring你是個什么東西,你需要什么東西,然后spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的創建、銷毀都由 spring來控制,也就是說控制對象生存周期的不再是引用它的對象,而是spring。DI(依賴注入)其實就是IOC的另外一種說法,其實它們是同一個概念的不同角度描述。
場景:
正常情況下我們使用一個對象時都是需要new Object() 的。而ioc是把需要使用的對象提前創建好,放到spring的容器里面。需要使用的時候直接使用就行,而且可以設置單例或多例,非常靈活。
我們在service層想調用另外一個service的方法,不需要去new了,直接把它交給spring管理,然后用注解的方式引入就能使用。
IOC三種注入方式
(1)XML:Bean實現類來自第三方類庫,例如DataSource等。需要命名空間等配置,例如:context,aop,mvc。
(2)注解:在開發的類使用@Controller,@Service等注解
(3)Java配置類:通過代碼控制對象創建邏輯的場景。例如:自定義修改依賴類庫。
什么是事務?
事務是訪問并可能更新數據庫中各種數據項的一個程序執行單元。
Spring事務與數據庫事務關系?
Spring的事務是對數據庫的事務的封裝,最后本質的實現還是在數據庫,假如數據庫不支持事務的話,Spring的事務是沒有作用的。所以說Spring事務的底層依賴MySQL的事務,Spring是在代碼層面利用AOP實現,執行事務的時候使用TransactionInceptor進行攔截,然后處理。本質是對方法前后進行攔截,然后在目標方法開始之前創建或者加入一個事務,執行完目標方法之后根據執行的情況提交或者回滾。
屬性(特性)
A(原子性):要么全部完成,要么完全不起作用
C(一致性):一旦事務完成(不管成功還是失敗),業務處于一致的狀態,而不會是部分完成,部分失敗。
I(隔離性):多事務會同時處理相同的數據,因此每個事務都應該與其他事務隔離開來,防止數據損壞。
D(持久性):一旦事務完成,無論發生什么系統錯誤,它的結果都不應該受到影響,事務的結果被寫到持久化存儲器中。
什么叫事務傳播行為?
傳播,至少有兩個東西,才可以發生傳播。單體不存在傳播這個行為。事務傳播行為就是當一個事務方法被另一個事務方法調用時,這個事務方法應該如何進行。
Spring支持7中事務傳播行為
propagation_required(需要傳播):當前沒有事務則新建事務,有則加入當前事務
propagation_supports(支持傳播):支持當前事務,如果當前沒有事務則以非事務方式執行
propagation_mandatory(強制傳播):使用當前事務,如果沒有則拋出異常
propagation_nested(嵌套傳播):如果當前存在事務,則在嵌套事務內執行,如果當前沒有事務,則執行需要傳播行為。
propagation_never(絕不傳播):以非事務的方式執行,如果當前有事務則拋出異常
propagation_requires_new(傳播需要新的):新建事務,如果當前有事務則把當前事務掛起
propagation_not_supported(不支持傳播):以非事務的方式執行,如果當前有事務則把當前事務掛起
數據庫事務的隔離級別
數據庫事務的隔離級別有4個,由低到高依次為Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別可以逐個解決臟讀、不可重復讀、幻讀這幾類問題。
√: 可能出現 ×: 不會出現
注意:我們討論隔離級別的場景,主要是在多個事務并發的情況下,因此,接下來的講解都圍繞事務并發。
Read uncommitted 讀未提交
公司發工資了,領導把20000元打到廖志偉的賬號上,但是該事務并未提交,而廖志偉正好去查看賬戶,發現工資已經到賬,是20000元整,非常高興。可是不幸的是,領導發現發給廖志偉的工資金額不對,是16000元,于是迅速回滾了事務,修改金額后,將事務提交,最后廖志偉實際的工資只有16000元,廖志偉空歡喜一場。
出現上述情況,即我們所說的臟讀,兩個并發的事務,“事務A:領導給廖志偉發工資”、“事務B:廖志偉查詢工資賬戶”,事務B讀取了事務A尚未提交的數據。當隔離級別設置為Read uncommitted時,就可能出現臟讀,如何避免臟讀,請看下一個隔離級別。
Read committed 讀提交
廖志偉拿著工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉賬,把廖志偉工資卡的2000元轉到另一賬戶,并在廖志偉之前提交了事務,當廖志偉扣款時,系統檢查到廖志偉的工資卡已經沒有錢,扣款失敗,廖志偉十分納悶,明明卡里有錢,為何…
出現上述情況,即我們所說的不可重復讀,兩個并發的事務,“事務A:廖志偉消費”、“事務B:廖志偉的老婆網上轉賬”,事務A事先讀取了數據,事務B緊接了更新了數據,并提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。當隔離級別設置為Read committed時,避免了臟讀,但是可能會造成不可重復讀。大多數數據庫的默認級別就是Read committed,比如Sql Server , Oracle。如何解決不可重復讀這一問題,請看下一個隔離級別。
Repeatable read 重復讀
當廖志偉拿著工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),廖志偉的老婆就不可能對該記錄進行修改,也就是廖志偉的老婆不能在此時轉賬。這就避免了不可重復讀。廖志偉的老婆工作在銀行部門,她時常通過銀行內部系統查看廖志偉的信用卡消費記錄。有一天,她正在查詢到廖志偉當月信用卡的總消費金額(select sum(amount) from transaction where month = 本月)為80元,而廖志偉此時正好在外面胡吃海喝后在收銀臺買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction … ),并提交了事務,隨后廖志偉的老婆將廖志偉當月信用卡消費的明細打印到A4紙上,卻發現消費總額為1080元,廖志偉的老婆很詫異,以為出現了幻覺,幻讀就這樣產生了。當隔離級別設置為Repeatable read時,可以避免不可重復讀,但會出現幻讀。注:MySQL的默認隔離級別就是Repeatable read。
Serializable 序列化
Serializable是最高的事務隔離級別,同時代價也花費最高,性能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免臟讀、不可重復讀,還避免了幻像讀。
總結
以上是生活随笔為你收集整理的Spring的AOP和IOC是什么?使用场景有哪些?Spring事务与数据库事务,传播行为,数据库隔离级别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HashMap底层实现原理,红黑树,B+
- 下一篇: IDEA创建SpringBoot项目报错