一起來學大數據|Java中的動態代理,重中之重的進階基石

一起來學大數據|Java中的動態代理,重中之重的進階基石

我們之前學習到,類加載器是通過類的.classLoader()方法,將.class文件從我們的磁盤中加載到jvm虛擬機中,形成字節碼文件。

反射是通過類加載形成的字節碼文件,把類裡的信息映射成相應的類,並進行各自的操作。

今天,我們學到的動態代理技術使我們整個java學習中最關鍵也是最重要的一問技術,是我們之後學習Java框架的基礎,不會動態代理,那麼學習框架的時候是學不明白的。

接下來,讓我們一起來弄明白這個動態代理。

代理模式

其實大家都知道一些什麼汽車代理,微商代理或者是手機代理商,換句話說他們就是替商品的廠家買東西,廠家委託代理銷售期產品。

在這裡,我們不需要知道代理背後的廠家是誰,也就是委託者對我們不可見;而這些代理可能使用朋友圈為主題目標,這樣也相當於代理幫助廠家額外做了一次客戶的過濾。

在Java中我們把前者抽象為代理類,後者抽象為委託類(被代理類)。

一起來學大數據|Java中的動態代理,重中之重的進階基石

代理優點

一起來學大數據|Java中的動態代理,重中之重的進階基石

靜態代理

舉個簡單例子,大家都有交作業的經驗吧,那我我們的班長就是代理,班主任就是委託者。

我們首先建一個Person接口。這個接口就是學生(被代理類),和班長(代理類)的公共接口,他們都要去給老師交作業,而我們學生交作業的時候就可以讓班長來幫我們去做。

一起來學大數據|Java中的動態代理,重中之重的進階基石

person接口

Student類實現Person接口,在這裡我們讓學生具體實現上交作業這個動作。

一起來學大數據|Java中的動態代理,重中之重的進階基石

student類

StudentsProxy類,學生代理也就是班長的類,我們在這個類中實現了Person的接口,同時,代理類中還有一個學生對象,這樣學生就可以像班長提交作業,由班長替我們交作業。

一起來學大數據|Java中的動態代理,重中之重的進階基石

下面測試一下,運行結果就是,“女陶上交班主任作業”。

一起來學大數據|Java中的動態代理,重中之重的進階基石

在這裡如果班長想表揚我女陶,可以在班長的類直接加入,不需要在我源代碼裡面輸入。如下圖。

一起來學大數據|Java中的動態代理,重中之重的進階基石

這樣的操作,就是使用代理模式一個很大的優點。直白一點說,就是在Spring中的面向切面編程(AOP)。

動態代理

代理類在程序運行時創建的代理方式被成為動態代理。 在上面的例子中,我們可以看到,班長這個代理類是我們自己定義好的,在程序運行之前就提前編譯好讓我們使用的。

動態代理,顧名思義就是代理類在程序運行時根據我們給的指示動態生成的。


同樣的舉個例子:

我們想要在剛剛的交作業上面加一個簽到的方法,如果是一個交作業的方法前加,那我們直接加入就好,那麼如果還有很多的方法呢,是不是很麻煩,我們看看動態代理怎麼實現的。

這次我們改成上交班費。

一起來學大數據|Java中的動態代理,重中之重的進階基石

動態代理簡單實現

同樣的定義一個Person

一起來學大數據|Java中的動態代理,重中之重的進階基石

我們創建一個被代理的student類。

一起來學大數據|Java中的動態代理,重中之重的進階基石

我們使用時間檢測工具,計算出該方法的運行時間

一起來學大數據|Java中的動態代理,重中之重的進階基石

我們通過創建StuInvocationHandler類,並且實現InvocationHandler接口,這個類中有一個被代理對象的實例叫做target。

一起來學大數據|Java中的動態代理,重中之重的進階基石

而InvocationHandler中有一個invoke方法,所有執行代理對象的方法都會被替換成執行invoke方法。

我們在nvoke方法中執行被代理對象target的相應方法。在代理過程中,我們可以在真正執行被代理對象的方法前加入自己的東西去處理。

這也是Spring中的AOP實現的主要原理,這裡我們在這裡有關聯到一個同樣重要的Java中反射方面的基礎知識。

一起來學大數據|Java中的動態代理,重中之重的進階基石


我們把上面的工作完成之後,就可以具體來創建動態代理對象了,上面的例子簡單的介紹了我們該如何創建動態代理對象。

接下來我們看看簡化的方式創建動態代理對象:

一起來學大數據|Java中的動態代理,重中之重的進階基石

一起來學大數據|Java中的動態代理,重中之重的進階基石

我們在執行ProxyTest類的時候,我們想來回想一下,我們開始創建了一個需要被代理的同學張三,之後我們將張三對象傳給stuHandler,在我們創建這個代理stuProxy的時候,我們又將stuHandler作為了參數,最後執行StuInvocationHandler中的invoke方法。因此我們看到了下面這樣的運行結果。

一起來學大數據|Java中的動態代理,重中之重的進階基石

總結:

我們在剛剛開始就提到,動態代理的明顯優勢在它可以很便捷的統一的處理代理類的方法,並不需要修改每個代理類中的方法。

其中的原因就是我們所有被代理執行的方法,都是通過在InvocationHandler中的invoke方法調用的,所以只要在invoke的方法中我們做統一的處理,就可實現對所有的被代理的方法進行相同的操作了。

例如,我們在這裡寫的對方法的計時,我們只做了很少的代碼量就可以讓所有方法都去計算運算時間。

一起來學大數據|Java中的動態代理,重中之重的進階基石

上面就是我們對今天學習的動態代理,其中我們還了解了什麼事代理,靜態代理的一些例子。Spring的AOP的實現其實也是用了Proxy和InvocationHandler。

明天,我們繼續學習Java中的一些常用類。

今天的學習有幫助到大家的話,關注支持一下唄~

感謝堅持關注的朋友~

一起來學大數據|Java中的動態代理,重中之重的進階基石

世界很大,幸好有你~

歡迎在評論區留下你的問題或困惑,我將每天與你分享我的觀點和心得。

聚焦最新科技諮訊,探尋未來智能領域,我是Mario女陶。


分享到:


相關文章: