我們之前學習到,類加載器是通過類的.classLoader()方法,將.class文件從我們的磁盤中加載到jvm虛擬機中,形成字節碼文件。
反射是通過類加載形成的字節碼文件,把類裡的信息映射成相應的類,並進行各自的操作。
今天,我們學到的動態代理技術使我們整個java學習中最關鍵也是最重要的一問技術,是我們之後學習Java框架的基礎,不會動態代理,那麼學習框架的時候是學不明白的。
接下來,讓我們一起來弄明白這個動態代理。
代理模式
其實大家都知道一些什麼汽車代理,微商代理或者是手機代理商,換句話說他們就是替商品的廠家買東西,廠家委託代理銷售期產品。
在這裡,我們不需要知道代理背後的廠家是誰,也就是委託者對我們不可見;而這些代理可能使用朋友圈為主題目標,這樣也相當於代理幫助廠家額外做了一次客戶的過濾。
在Java中我們把前者抽象為代理類,後者抽象為委託類(被代理類)。
靜態代理
舉個簡單例子,大家都有交作業的經驗吧,那我我們的班長就是代理,班主任就是委託者。
我們首先建一個Person接口。這個接口就是學生(被代理類),和班長(代理類)的公共接口,他們都要去給老師交作業,而我們學生交作業的時候就可以讓班長來幫我們去做。
Student類實現Person接口,在這裡我們讓學生具體實現上交作業這個動作。
StudentsProxy類,學生代理也就是班長的類,我們在這個類中實現了Person的接口,同時,代理類中還有一個學生對象,這樣學生就可以像班長提交作業,由班長替我們交作業。
下面測試一下,運行結果就是,“女陶上交班主任作業”。
在這裡如果班長想表揚我女陶,可以在班長的類直接加入,不需要在我源代碼裡面輸入。如下圖。
這樣的操作,就是使用代理模式一個很大的優點。直白一點說,就是在Spring中的面向切面編程(AOP)。
動態代理
代理類在程序運行時創建的代理方式被成為動態代理。 在上面的例子中,我們可以看到,班長這個代理類是我們自己定義好的,在程序運行之前就提前編譯好讓我們使用的。
動態代理,顧名思義就是代理類在程序運行時根據我們給的指示動態生成的。
同樣的舉個例子:
我們想要在剛剛的交作業上面加一個簽到的方法,如果是一個交作業的方法前加,那我們直接加入就好,那麼如果還有很多的方法呢,是不是很麻煩,我們看看動態代理怎麼實現的。
這次我們改成上交班費。
動態代理簡單實現
同樣的定義一個Person
我們創建一個被代理的student類。
我們使用時間檢測工具,計算出該方法的運行時間
我們通過創建StuInvocationHandler類,並且實現InvocationHandler接口,這個類中有一個被代理對象的實例叫做target。
而InvocationHandler中有一個invoke方法,所有執行代理對象的方法都會被替換成執行invoke方法。
我們在nvoke方法中執行被代理對象target的相應方法。在代理過程中,我們可以在真正執行被代理對象的方法前加入自己的東西去處理。
這也是Spring中的AOP實現的主要原理,這裡我們在這裡有關聯到一個同樣重要的Java中反射方面的基礎知識。
我們把上面的工作完成之後,就可以具體來創建動態代理對象了,上面的例子簡單的介紹了我們該如何創建動態代理對象。
接下來我們看看簡化的方式創建動態代理對象:
我們在執行ProxyTest類的時候,我們想來回想一下,我們開始創建了一個需要被代理的同學張三,之後我們將張三對象傳給stuHandler,在我們創建這個代理stuProxy的時候,我們又將stuHandler作為了參數,最後執行StuInvocationHandler中的invoke方法。因此我們看到了下面這樣的運行結果。
總結:
我們在剛剛開始就提到,動態代理的明顯優勢在它可以很便捷的統一的處理代理類的方法,並不需要修改每個代理類中的方法。
其中的原因就是我們所有被代理執行的方法,都是通過在InvocationHandler中的invoke方法調用的,所以只要在invoke的方法中我們做統一的處理,就可實現對所有的被代理的方法進行相同的操作了。
例如,我們在這裡寫的對方法的計時,我們只做了很少的代碼量就可以讓所有方法都去計算運算時間。
上面就是我們對今天學習的動態代理,其中我們還了解了什麼事代理,靜態代理的一些例子。Spring的AOP的實現其實也是用了Proxy和InvocationHandler。
明天,我們繼續學習Java中的一些常用類。
今天的學習有幫助到大家的話,關注支持一下唄~
感謝堅持關注的朋友~
世界很大,幸好有你~
歡迎在評論區留下你的問題或困惑,我將每天與你分享我的觀點和心得。
聚焦最新科技諮訊,探尋未來智能領域,我是Mario女陶。
閱讀更多 女陶愛柚子 的文章