纽伦堡德甲 纽伦堡德甲
當前位置:纽伦堡德甲 > 纽伦堡德甲 >  創業

多特蒙德纽伦堡:Java 動態代理詳解

纽伦堡德甲 www.hnarto.com.cn 2020-03-21 17:49:36 木莊網絡博客 編輯:草根 瀏覽數:6纽伦堡德甲

本文摘自掘金-小旋鋒,原文地址:https://juejin.im/post/5c1ca8df6fb9a049b347f55c,轉載內容有刪減,侵刪。 動態代理在Java中有著廣泛的應用,比如Spring ...

本文摘自掘金-小旋鋒,原文地址:https://juejin.im/post/5c1ca8df6fb9a049b347f55c,轉載內容有刪減,侵刪。

動態代理在Java中有著廣泛的應用,比如Spring AOP、Hibernate數據查詢、測試框架的后端mock、RPC遠程調用、Java注解對象獲取、日志、用戶鑒權、全局性異常處理、性能監控,甚至事務處理等。

本文主要介紹Java中兩種常見的動態代理方式:JDK原生動態代理CGLIB動態代理。

由于Java動態代理與java反射機制關系緊密,請讀者確保已經了解了Java反射機制,可參考上一篇文章《Java反射機制詳解》。

代理模式

本文將介紹的Java動態代理與設計模式中的代理模式有關,什么是代理模式呢?

代理模式:給某一個對象提供一個代理,并由代理對象來控制對真實對象的訪問。代理模式是一種結構型設計模式。

代理模式角色分為 3 種:

Subject(抽象主題角色):定義代理類和真實主題的公共對外方法,也是代理類代理真實主題的方法;

RealSubject(真實主題角色):真正實現業務邏輯的類;

Proxy(代理主題角色):用來代理和封裝真實主題;

代理模式的結構比較簡單,其核心是代理類,為了讓客戶端能夠一致性地對待真實對象和代理對象,在代理模式中引入了抽象層。

代理模式按照職責(使用場景)來分類,至少可以分為以下幾類:

1、遠程代理。 

2、虛擬代理。 

3、Copy-on-Write 代理。 

4、?;ぃ≒rotect or Access)代理。 

5、Cache代理。 

6、防火墻(Firewall)代理。 

7、同步化(Synchronization)代理。 

8、智能引用(Smart Reference)代理等等。 

如果根據字節碼的創建時機來分類,可以分為靜態代理和動態代理: 

· 所謂靜態也就是在程序運行前就已經存在代理類的字節碼文件,代理類和真實主題角色的關系在運行前就確定了。 

· 而動態代理的源碼是在程序運行期間由JVM根據反射等機制動態的生成,所以在運行前并不存在代理類的字節碼文件。

靜態代理

我們先通過實例來學習靜態代理,然后理解靜態代理的缺點,再來學習本文的主角:動態代理。

編寫一個接口 UserService ,以及該接口的一個實現類 UserServiceImpl

public interface UserService {
    public void select();   
    public void update();
}

public class UserServiceImpl implements UserService {  
    public void select() {  
        System.out.println("查詢 selectById");
    }
    public void update() {
        System.out.println("更新 update");
    }
}

我們將通過靜態代理對 UserServiceImpl 進行功能增強,在調用 selectupdate 之前記錄一些日志。

寫一個代理類 UserServiceProxy,代理類需要實現 UserService

public class UserServiceProxy implements UserService {
    private UserService target; // 被代理的對象

    public UserServiceProxy(UserService target) {
        this.target = target;
    }
    public void select() {
        before();
        target.select();    // 這里才實際調用真實主題角色的方法
        after();
    }
    public void update() {
        before();
        target.update();    // 這里才實際調用真實主題角色的方法
        after();
    }

    private void before() {     // 在執行方法之前執行
        System.out.println(String.format("log start time [%s] ", new Date()));
    }
    private void after() {      // 在執行方法之后執行
        System.out.println(String.format("log end time [%s] ", new Date()));
    }
}

客戶端測試

public class Client1 {
    public static void main(String[] args) {
        UserService userServiceImpl = new UserServiceImpl();
        UserService proxy = new UserServiceProxy(userServiceImpl);

        proxy.select();
        proxy.update();
    }
}

輸出

log start time [Thu Dec 20 14:13:25 CST 2018] 
查詢 selectById
log end time [Thu Dec 20 14:13:25 CST 2018] 
log start time [Thu Dec 20 14:13:25 CST 2018] 
更新 update
log end time [Thu Dec 20 14:13:25 CST 2018] 

通過靜態代理,我們達到了功能增強的目的,而且沒有侵入原代碼,這是靜態代理的一個優點。 

靜態代理的缺點

雖然靜態代理實現簡單,且不侵入原代碼,但是,當場景稍微復雜一些的時候,靜態代理的缺點也會暴露出來。 

1、 當需要代理多個類的時候,由于代理對象要實現與目標對象一致的接口,有兩種方式: 

· 只維護一個代理類,由這個代理類實現多個接口,但是這樣就導致代理類過于龐大

· 新建多個代理類,每個目標對象對應一個代理類,但是這樣會產生過多的代理類

2、 當接口需要增加、刪除、修改方法的時候,目標對象與代理類都要同時修改,不易維護。 

如何改進?

當然是讓代理類動態的生成啦,也就是動態代理。

為什么類可以動態的生成?

這就涉及到Java虛擬機的類加載機制了,推薦翻看《深入理解Java虛擬機》7.3節 類加載的過程。

Java虛擬機類加載過程主要分為五個階段:加載、驗證、準備、解析、初始化。

其中加載階段需要完成以下3件事情:

1. 通過一個類的全限定名來獲取定義此類的二進制字節流

2. 將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構

3. 在內存中生成一個代表這個類的 java.lang.Class 對象,作為方法區這個類的各種數據訪問入口

由于虛擬機規范對這3點要求并不具體,所以實際的實現是非常靈活的,關于第1點,獲取類的二進制字節流(class字節碼)就有很多途徑:

· 從ZIP包獲取,這是JAR、EAR、WAR等格式的基礎

· 從網絡中獲取,典型的應用是 Applet

· 運行時計算生成,這種場景使用最多的是動態代理技術,在 java.lang.reflect.Proxy 類中,就是用了 ProxyGenerator.generateProxyClass 來為特定接口生成形式為 *$Proxy 的代理類的二進制字節流

· 由其它文件生成,典型應用是JSP,即由JSP文件生成對應的Class類

· 從數據庫中獲取等等

所以,動態代理就是想辦法,根據接口或目標對象,計算出代理類的字節碼,然后再加載到JVM中使用。

分享到:

版權與免責聲明:

凡未注明"稿件來源"的內容均為轉載稿,本網轉載出于傳遞更多信息的目的;如轉載稿涉及版權問題,請作者聯系我們,同時對于用戶評論等信息,本網并不意味著贊同其觀點或證實其內容的真實性;


本文地址://www.hnarto.com.cn/news/2020/03/21/62351338.html

轉載本站原創文章請注明來源:纽伦堡德甲

行業聚焦

寧德時代聯合百城新能源成立新公司 涉及新能源科技、電池科技等業務

據天眼查數據顯示,近日,寧德時代聯合百城新能源成立了新公司,涉及了新能源科技、電池科技等業務。上??觳沸履茉純萍加邢薰境閃?,該公司注冊資本5000萬元,法定代...[詳細]

三星折疊屏手機Galaxy Z Flip不會重蹈覆轍的五個原因

據國外媒體Mashable分析,三星Galaxy Z Flip將會比上一款折疊屏手機Galaxy Fold更成功,不再會重蹈去年折疊屏手機的質量問題及叫好不叫座...[詳細]

特斯拉:無鈷,不代表一定是磷酸鐵鋰電池

近日,有報道稱,特斯拉將采用磷酸鐵鋰電池,對此特斯拉在官方抖音號上表示:”請留意四月特斯拉的電池發布會,無鈷,不代表一定是磷酸鐵鋰?!閉饌品舜飼巴飩緄牟虜?,認...[詳細]

寧德時代:已與特斯拉簽訂量產供貨定價協議

此前,網上爆出寧德時代與特斯拉的合作等事宜,對此,寧德時代回應稱,已與特斯拉簽訂量產供貨定價協議。此前,特斯拉與寧德時代商討在國產版電動汽車上使用無鈷電池,談判...[詳細]

蘋果新款 Powerbeats 耳機國行上架:1199元

強勁性能,伴你左右Powerbeats 高性能無線耳機搭載 Apple H1 耳機芯片,激勵你不斷前行??傻鶻詰姆闌胰繁E宕魘媸飾裙?,增強的抗汗抗水設計則讓...[詳細]

科技趨勢

更多

正式發布S20/Ultra 5G和Z Flip折疊屏手機,三星走上復興之路

 

2月12日消息,據外媒報道,美國當地時間周二,三星電子公司在舊金山發布了其最新款智能手機,希望能幫助公司實現復興。這些手...[詳細]

微軟公布GDC 2020直播活動時間表:含Xbox新主機專場

 

IT之家3月10日消息 微軟通過官方博客宣布,將于當地時間3月17日至18日在Mixer直播平臺,與業內人士分...[詳細]

V社打算重啟《Artifact》:直面失敗,從頭再來

 

IT之家3月21日消息 V社的CCG/策略游戲《Artifact》是比較失敗的,但這并不意味著他們已經放棄了在...[詳細]

馬云“求轉發”:成立在線健康咨詢平臺,為海外同胞提供防治咨詢

 

IT之家3月23日消息 今日上午馬云通過個人官方微博發文稱,馬云公益基金會和阿里巴巴公益基金會緊急搭建了一個“...[詳細]

【IT之家開箱】OPPO Find X2 Pro茶橘圖賞

 

IT之家3月6日消息 今天下午,OPPO正式發布新款OPPO Find X2系列手機,全系搭載了驍龍865處理...[詳細]

一周排行每月關注
万银鼎信配资 河北十一选五开奖走 快3计划软件 股票涨跌 睿新配资 配资平台哪个好专业天牛宝 天津福彩快乐10分开奖结果查询 股票融资公司靠谱认准大牛时代 快乐10分钟一 根据投资所选标的的差异股票指数投资策略 甘肃快三今天开奖情况 互联网理财平台大全 新快3计划软件 股票配资平台有哪些 山东11选5助手 三明配资炒股