前面講到了動態代理的底層原理,接下來咱們來看一下aop的動態代理.
Spring AOP使用了兩種代理機制:一種是基於JDK的動態代理,一種是基於CGLib的動態代理.spring
①JDK動態代理:使用JDK建立代理有一個限制,它只能爲接口建立代理實例.這一點能夠從Proxy的接口方法
newProxyInstance(ClassLoader loader,Class [] interfaces,InvocarionHandler h)中看的很清楚
第二個入參 interfaces就是須要代理實例實現的接口列表.
②CGLib:採用底層的字節碼技術,能夠爲一個類建立子類,在子類中採用方法攔截的技術攔截全部父類方法的調用
並順勢織入橫切邏輯.
③對比:CGLib所建立的動態代理對象的性能比JDK的高大概10倍,但CGLib在建立代理對象的時間比JDK大概多8倍,因此對於singleton的代理對象或者具備實例池的代理,由於無需重複的建立代理對象,因此比較適合CGLib動態代理技術,反之選擇JDK代理。值得一提的是因爲CGLib採用動態建立子類的方式生成代理對象,因此不能對目標類中final的方法進行代理。性能
可是這種實現方式存在三個明顯須要改進的地方:this
a.目標類的全部方法都添加了橫切邏輯,而有時,這並非咱們所指望的,咱們可能只但願對業務類中的某些特定的方法添加橫切邏輯;編碼
b.咱們經過硬編碼的方式制定了織入橫切邏輯的織入點,即在目標業務方法的開始和結束前織入代碼;spa
c.咱們手工編寫代理實例的建立過程,爲不一樣類建立代理時,須要分別編寫相應的建立代碼,沒法作到通用;debug
還有一個問題是:spring依賴注入時,何時會建立代理類,有時候是cglib有時候是jdkproxy有時候只是普通實例,有興趣的能夠查閱資料,getBean依賴注入過程,可查看IOC源碼。代理
下面咱們舉個例子看看aop事務註解是怎麼實現的。
JDK動態代理:aop中生成的代理類是JdkDynamicAopProxy子類,debug調試的時候能夠看到,打開源碼可看到實現了AopProxy和invocationHandler也就實現invoke方法。
invoke關鍵代碼:調試
// Get the interception chain for this method.加載一系列的攔截器 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
TransactionInterceptor是事務攔截器,全部帶有@Transactional註解的方法都會通過攔截器invoke方法攔截,點進方法裏面能夠發現代碼以下:code
好比回滾方法點進去發現是獲取事務管理器而後回滾對象
最後看下靜態代理,JDK動態代理及cglib動態代理的對比