2020-01-07動(dòng)態(tài)代理

個(gè)人日記:不建議購買

一、代理模式的第一個(gè)版本:靜態(tài)代理

如圖所示:


圖片.png

圖中反應(yīng)的本質(zhì):

  • 代理對(duì)象和被代理對(duì)象實(shí)現(xiàn)相同的接口。
  • 代理對(duì)象中包含被代理對(duì)象。
    (不禁感嘆:靜態(tài)代理和裝飾器模式好像啊?。。?/li>

代碼表現(xiàn):

Class ProxyObject implements A,B,C{
  private A a;
  private B b;
  private C c;
//在方法中調(diào)用具體對(duì)象a,b,c的方法并且對(duì)方法進(jìn)行增強(qiáng)

}
靜態(tài)代理的測(cè)試方法.png

靜態(tài)代理存在的問題:

  • 代碼的冗余
  • 不符合開閉原則,所謂開閉原則是指對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉(當(dāng)我們的需求發(fā)生變化的時(shí)候,我們通過添加新的模塊來滿足新的需求,而不是通過修改原來的代碼來滿足)。這個(gè)原則是六個(gè)設(shè)計(jì)原則中最重要的。

如果不滿足單一原則會(huì)發(fā)生

  • 可讀性變差
  • 可維護(hù)性變差(代碼耦合性比較高),只要有一個(gè)功能模塊發(fā)生了變化,代理類就會(huì)出錯(cuò),牽一發(fā)動(dòng)全身,代理類也沒法為其他的模塊提供服務(wù)了。

靜態(tài)代理作為代理模式的第一個(gè)實(shí)現(xiàn)版本,存在以上比較嚴(yán)重的問題。違反了開閉原則。

二、代理模式的第二個(gè)版本:動(dòng)態(tài)代理

代理:代理模式
動(dòng)態(tài):???

靜態(tài)代理和動(dòng)態(tài)代理的類圖是一毛一樣的??!對(duì)于動(dòng)態(tài)代理來說,它的代理對(duì)象不再是一個(gè)固定的對(duì)象,而是一個(gè)動(dòng)態(tài)的對(duì)象。可以在使用的時(shí)候進(jìn)行動(dòng)態(tài)的生成。

圖片.png

Proxy:調(diào)度各種員工進(jìn)行服務(wù)
查看源碼看proxy的功能:

InvocationHandler:本質(zhì)就是對(duì)服務(wù)進(jìn)行增強(qiáng)

這里體現(xiàn)了單一職責(zé)的原則:

  • Proxy僅僅負(fù)責(zé)創(chuàng)建對(duì)象;
  • InvocationHandler負(fù)責(zé)實(shí)例做的事情;

方法增強(qiáng)的類中含有被代理對(duì)象:
下面的例子中使用接口是面向接口編程,解耦


圖片.png
圖片.png

這里使用反射去調(diào)用運(yùn)行的方法,因?yàn)椴恢谰烤故悄膫€(gè)被代理對(duì)象在運(yùn)行。


圖片.png

關(guān)于類加載器,不同的類加載器可以隨便使用嗎?還有,繼承關(guān)系的兩個(gè)類,類加載器一樣嗎??


圖片.png

這樣的話使用一套代碼就能夠滿足所有的需求。

二、深入內(nèi)核剖析

解密事務(wù)注解

我們可以發(fā)現(xiàn)代理對(duì)象的名稱是$Proxy+數(shù)字。
這種名字是內(nèi)部類

接下來探索這兩個(gè)類究竟是什么,發(fā)現(xiàn)它們不曾出現(xiàn)在文件中,那么是怎樣產(chǎn)生的呢??
首先來看一下類的生命周期:


圖片.png

編譯使用的命令:javac XXX.java
java的跨平臺(tái)性質(zhì)也是因?yàn)樽止?jié)碼技術(shù)。
Class對(duì)象存在于JVM的方法區(qū)或者叫元空間,在jdk1.8之前是方法區(qū),后來叫做元空間。
實(shí)例對(duì)象在堆上。
可達(dá)性分析可以幫助判斷這個(gè)類需不需要進(jìn)行回收。

面試的問題形式:
不會(huì)問你有什么垃圾回收算法或者垃圾回收器,而是問你在你的項(xiàng)目中使用了什么垃圾回收算法,為什么使用這種垃圾回收算法和回收器。它有什么優(yōu)點(diǎn)。

動(dòng)態(tài)代理忽略了java文件,直接生成的就是java字節(jié)碼,java字節(jié)碼有兩種來源,一種是硬盤,一種是內(nèi)存。

tomcat的類熱加載機(jī)制???從網(wǎng)絡(luò)中傳輸字節(jié)碼
mapper的實(shí)際實(shí)現(xiàn)原理??

1、怎樣在內(nèi)存中生成字節(jié)碼?
內(nèi)存中生成的字節(jié)碼究竟是什么樣子??
Proxy.newInstance()進(jìn)行分析。

分析代碼Class<?> cl = getProxyClass0(loader,intfs),這句代碼完成兩件事情:

  1. 在JVM中生成了字節(jié)碼
  2. 將字節(jié)碼文件加載成了Class對(duì)象。

native方法,直接調(diào)用操作系統(tǒng)的類庫生成的方法。用c或者是c++寫的。

那么生成代碼的結(jié)構(gòu)是什么樣呢??
使用反編譯工具看一看這個(gè)類究竟是什么樣子的。


圖片.png
圖片.png
圖片.png

產(chǎn)生的所有Proxy對(duì)象都是Proxy的子類對(duì)象


圖片.png

使用動(dòng)態(tài)代理解析spring相關(guān)的注解源碼:

面試題:
1、spring事務(wù)注解的實(shí)現(xiàn)原理?
為什么加了@Transactional注解之后,方法就有了事務(wù)的能力?
首先是JdkDynamicAopProxy,其中有一個(gè)方法,這個(gè)方法會(huì)經(jīng)過一系列的攔截器鏈,然后是TransactionaIntercepter這個(gè)攔截器,在這個(gè)攔截器中實(shí)現(xiàn)了方法前的事務(wù)開啟,方法后的事務(wù)結(jié)束,出現(xiàn)異常的回滾操作。

2、為什么Mybatis可以直接使用mapper接口訪問數(shù)據(jù)庫?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容