代理模式:spring
客戶:租一間好的房子(便宜的)express
MIS(代理人):找房子,看房子,租房子,交中介費編程
房東:房東出租房屋。模塊化
代理模式的特徵:spa
1.代理者(Proxy)必須實現和被代理者(房東)相同的接口(這樣看起來才能和被代理者如出一轍)代理
2.在完成客戶要求之後,還要作其餘的操做(收取中介費)日誌
2.靜態代理模式(一種思想)xml
2.1說明:對象
事務模塊是系統開發過程當中必不可少的模塊。會有專門的團隊或負責人來負責。但是一旦事務模塊和業務模塊交織在一塊兒,就會形成代碼的緊耦合。接口
理想模式:
事務模塊的代碼只處理事務的方法,而業務模塊代碼只處理業務,
二者之間最好不要有直接的聯繫。不然代碼的耦合性較高,後期不易於維護和擴展。
2.1使用靜態代理模式解決緊耦合的問題
經過靜態代理模式:能夠實現業務和事務方法相分離。解決了兩者之間的耦合性問題。
問題:雖然可以解決耦合性問題。可是重複代理量較多。每寫一個方法都必須添加事務的相關代碼。實質上就是代碼的遷移,沒有作到代碼的重用和靈活。代理對象只能代理一個接口。
3.動態代理模式
JDK的動態代理
被代理者必須實現接口,若是沒有實現接口那麼JDK就不能生成代理對象。生成代理對象的速度較快
Cglib的動態代理
1.被代理者有無接口都能生成代理對象。
2.生成的代理對象都是被代理者的子類。
3.內部生經過二進制碼來幫助生成代理對象,全部對象的生成速度很慢。可是一旦生成了代理對象。執行速度很快。
4.JDK的動態代理
可以生成代理對象 其class形式
class com.sun.proxy.$Proxy6
5.Cglib的動態代理
//加強器
Enhancer enhancer = new Enhancer();
//傳入接口
enhancer.setInterfaces(target.getClass().getInterfaces());
//設置父類 必須
enhancer.setSuperclass(target.getClass());
//設置回調
enhancer.setCallback(new MethodInterceptor()
CGlib對象的類型
class service.PersonServiceImpl$$EnhancerByCGLIB$$ea3089c1
Spring內部集成了Cglib
6.SpringAOP
面向切面編程 一種思想
6.1名詞解釋
1.切面(Aspect):一個關注點的模塊化,這個關注點可能會橫切多個對象。
一個切面就是在完成目標方法後再執行其操做的程序代碼
2.鏈接點(Joinpoint):在程序執行過程當中某個特定的點
就是客戶端調用的目標方法。
3.通知(Advice):在切面的某個特定的鏈接點上執行的動做。
就是切面中的方法。
4.切入點(Pointcut):匹配鏈接點的斷言
切入點就是一個匹配切面的過程
5.目標對象(Target Object): 被一個或者多個切面所通知的對象。
就是真正執行目標方法的對象
6.織入(Weaving):把切面鏈接到其它的應用程序類型或者對象上,並建立一個被通知的對象。
造成切面的過程就是織入。
6.2AOP的入門
步驟:
1.配置頭文件 導入約束
xmlns:aop="http://www.springframework.org/schema/aop"
2.導入相關的開發jar包5個
3.配置自定義的切面
4.xml配置的順序
Content Model : (pointcut*, advisor*, aspect*)
<aop:config>
<!--配置切入點 -->
<aop:pointcut expression="within(service.*)" id="pc"/>
<aop:aspect ref="myAspect">
<!--配置通知的方法 -->
<aop:around method="around" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
6.3:AOP的原理
當建立對象的時候首先spring和和切入點表達式進行匹配。若是匹配成功。則建立代理對象。咱們客戶端拿到代理對象後看上去和目標對象如出一轍。//????
調用目標對象執行方法。就會執行切面中的通知(方法)。利用代理對象完成一些額外的操做。最終執行目標方法。
6.4:通知的類型
1.環繞通知(Around Advice):在目標方法執行以前。執行以後都須要執行額外操做的通知。
2.前置通知(Before advice):在目標方法執行以前的操做。
3.後置通知(After returning advice):在目標方法執行以後執行的通知
4.異常通知(After throwing advice):在執行目標方法時,若是目標方法報錯就會被異常通知攔截,這時異常通知纔會執行。
5.最終通知(After (finally) advice):無論如何都會執行最終通知。
6.5 異常的處理
在Spring中異常的try--catch不能隨便加,若是添加了try-catch那麼spring容器就捕獲不到。不能作出正確的處理。若是想寫try-catch那麼異常捕獲時要具體指明某一類的異常 不能使用Exception,由於這個異常捕獲能力太強。
6.6通知的處理順序
當目標方法執行拋出異常時 異常通知會被執行,後置通知不會被調用。
6.7通知的使用場景
1.環繞通知:我是不須要目標方法執行,而且執行先後有必要的操做。
2.前置通知:日誌收集????? 前置通知執行不能影響目標方法是否被執行 與它毫無關係。
3.後置通知:若是須要對目標方法的返回值結果作操做 可使用後置通知。通知也不能影響目標方法的執行。
4.異常通知:能夠對異常作收集 之後使用異常通知。
5.最終通知:能夠用來關閉一些連接或者釋放資源。
6.8通知中的參數
除了環繞通知以外其餘的通知都是JoinPoint。而且全部的參數都必須位於第一位。
而環繞通知中 必須添加ProceedingJoinPoint 由於 只有ProceedingJoinPoint類中有proceed方法。才能讓目標方法執行。
6.9關於表達式的寫法
within(service.*)
它是一個類級別的表達式,能夠按照類型來匹配。匹配的規則包名+類名。
若是想匹配該包下的全部子類 用*代替。 若是想匹配該包下的全部子孫類用
..*表示。
execution(返回值結果 包名.類名.方法名(參數名))
execution(* service..*(..))
表達式建立代理對象的原理;
只有知足表達式要求的纔會被建立代理對象,可以精確到方法和參數級別。