【Spring篇】JDK動態代理

目錄

什么是代理?

代理模式

動態代理

Java中常用的代理模式

問題來了,如何動態生成代理類?

動態代理底層實現


什么是代理?

顧名思義,代替某個對象去處理一些問題,謂之代理,那么何為動態?即讓JVM虛擬機去完成而非程序員去完成(與靜態對比),連起來就是讓虛擬機去動態的創建一個對象去代替另一個對象完成某些業務需求

呢么其中就涉及到了兩個對象,代理類目標類;代理類又被前輩歸納成代理模式,下面看代理模式;

代理模式

代理模式是GoF23種設計模式之一。屬于結構型設計模式。

代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個客戶不想或者不能直接引用一個對象,此時可以通過一個稱之為“代理”的第三者來實現間接引用。代理對象可以在客戶端和目標對象之間起到中介的作用,并且可以通過代理對象去掉客戶不應該看到的內容和服務或者添加客戶需要的額外服務。 通過引入一個新的對象來實現對真實對象的操作或者將新的對象作為真實對象的一個替身,這種實現機制即為代理模式,通過引入代理對象來間接訪問一個對象,這就是代理模式的模式動機。

代理模式中的角色:

  • 代理類(代理主題)
  • 目標類(真實主題)
  • 代理類和目標類的公共接口(抽象主題):客戶端在使用代理類時就像在使用目標類,不被客戶端所察覺,所以代理類和目標類要有共同的行為,也就是實現共同的接口。

為什么要有個公共接口呢?

呢你代理類要代替目標類完成某些操作,你是不是就需要擁有目標類該有的功能,如何擁有這個類擁有的功能呢?一、代理類繼承目標類(但是繼承太死板,耦合度太高,而且當需求量上去后,你是不是要寫n個子類,不明智!!!)二、通過實現共同接口,實現必要方法,nice!!!,完美解決;

?知道基本概念后,我們完善一下,用更加官方的話來表示。。。

動態代理

在程序運行階段,在內存中動態生成代理類,被稱為動態代理,目的是為了減少代理類的數量。解決代碼復用的問題。

Java中常用的代理模式

  • jdk動態代理;
  • cglib靜態代理;
  • Javassist動態代理技術;

?我們主要分析JDK代理技術

JDK動態代理(理解):使用java反射包中的類和接口實現動態代理的功能,反射包java.lang.reflect,里面有三個類:InvocationHandler,Method,Proxy


?|? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??下面我們通過一個實際業務需求來分析動態代理? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|


假設某項目已上線,并且運行正常,只是客戶反饋系統有一些地方運行較慢,要求項目組對系統進行優化。于是項目負責人就下達了這個需求。首先需要搞清楚是哪些業務方法耗時較長,于是讓我們統計每個業務方法所耗費的時長。你坑定不能直接在已經上線并且運行很好的項目的源代碼上操作啊,于是乎我們采用靜態代理方法,代碼如下:

// 目標接口
public interface OrderService {void add();void update();void delete();
}
// 目標類
public class OrderServiceImpl implements OrderService {@Overridepublic void add() {System.out.println("添加用戶");}@Overridepublic void update() {System.out.println("修改用戶");}@Overridepublic void delete() {System.out.println("刪除用戶");}
}
// 代理類
public class OrderServiceProxy implements OrderService {@Overridepublic void add() {long begin = System.currentTimeMillis();OrderService.add();long end = System.currentTimeMillis();System.out.println("耗時"+(end - begin)+"毫秒");}@Overridepublic void update() {long begin = System.currentTimeMillis();OrderService.update();long end = System.currentTimeMillis();System.out.println("耗時"+(end - begin)+"毫秒");}@Overridepublic void delete() {long begin = System.currentTimeMillis();OrderService.delete();long end = System.currentTimeMillis();System.out.println("耗時"+(end - begin)+"毫秒");}
}

在上面的靜態代理方法中,代理類和目標類都實現同一個接口,在代理類中維護目標類對象,并完成對目標類對象方法的增強,這種方式雖然遵循開閉原則,但是代理類和目標類至少是“一對一”的綁定關系,如果需要被代理的目標類個數越多,代理類就會越多,會產生大量重復的代碼,也不利于后期的維護。

于是乎我們使用動態代理技術:目前代碼是這樣的,需要我們動態生成一個代理類:

// 目標接口
public interfaceOrderService {void add();void update();void delete();
}
// 目標類
public class OrderServiceImpl implements OrderService {@Overridepublic void add() {System.out.println("添加用戶");}@Overridepublic void update() {System.out.println("修改用戶");}@Overridepublic void delete() {System.out.println("刪除用戶");}
}

問題來了,如何動態生成代理類?

回歸到文章中心題目,JDK動態代理技術

在JDK中,有一個Proxy類,Proxy類是專門完成代理的操作類,可以通過此類為一個或多個接口動態的生成實現類。這個類有一個靜態方法:newProxyInstance()方法。這個方法的目的就是給我們的目標對象返回一個代理對象。

我們可以看到其中newProxyInstance()方法有三個參數,下面分析三個參數:

  • 第一個參數:類加載器。在內存中生成了字節碼,要想執行這個字節碼,也是需要先把這個字節碼加載到內存當中的。所以要指定使用哪個類加載器加載。
  • 第二個參數:接口類型。代理類和目標類實現相同的接口,所以要通過這個參數告訴JDK動態代理生成的類要實現哪些接口。
  • 第三個參數:調用處理器。這是一個JDK動態代理規定的接口,接口全名:java.lang.reflect.InvocationHandler。顯然這是一個回調接口,也就是說調用這個接口中方法的程序已經寫好了,就差這個接口的實現類了。

所以接下來我們要寫一下java.lang.reflect.InvocationHandler接口的實現類,并且實現接口中的方法,代碼如下:

public class TimerInvocationHandler implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return null;}
}

InvocationHandler接口中有一個方法invoke,這個invoke方法上有三個參數:

  • 第一個參數:Object proxy。代理對象。設計這個參數只是為了后期的方便,如果想在invoke方法中使用代理對象的話,盡管通過這個參數來使用。
  • 第二個參數:Method method。目標方法。
  • 第三個參數:Object[] args。目標方法調用時要傳的參數。

我們將來肯定是要調用“目標方法”的,但要調用目標方法的話,需要“目標對象”的存在,“目標對象”從哪兒來呢?我們可以給TimerInvocationHandler提供一個構造方法,可以通過這個構造方法傳過來“目標對象”,代碼如下:

public class TimerInvocationHandler implements InvocationHandler {// 目標對象private Object target;// 通過構造方法來傳目標對象public TimerInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 目標執行之前增強。long begin = System.currentTimeMillis();// 調用目標對象的目標方法Object retValue = method.invoke(target, args);// 目標執行之后增強。long end = System.currentTimeMillis();System.out.println("耗時"+(end - begin)+"毫秒");// 一定要記得返回哦。return retValue;}
}

接下來我們開始調用:

 // 創建目標對象OrderService target = new OrderServiceImpl();// 創建代理對象OrderService orderServiceProxy = (OrderService) ProxyUtil.newProxyInstance(target);// 調用代理對象的代理方法orderServiceProxy.add();orderServiceProxy.update();orderServiceProxy.delete();

?成功;

動態代理底層實現

現在我們思考一個問題:在使用動態代理之前,我們有一個目標類、一個公共接口;我們如何通過二者和proxy類返回一個代理類對象呢?

我們知道創建一個對象就先要有這個類才能new對象,那現在代理類都還不存在,該怎么去構造代理對象呢?

JDK動態代理的目的就是通過接口來生成代理類以及代理類的對象,我們知道接口是不能直接通過new關鍵字創建對象的。那么JDK動態代理是怎么創建出代理類以及代理類對象的呢?
?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/167367.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167367.shtml
英文地址,請注明出處:http://en.pswp.cn/news/167367.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

短視頻賬號矩陣系統saas化批量管理部署搭建/技術

一、短視頻矩陣系統建模----技術api接口--獲取用戶授權 技術文檔分享: 本系統采用MySQL數據庫進行存儲,數據庫設計如下: 1.用戶表(user): - 用戶ID(user_id) - 用戶名(…

SELinux零知識學習二十七、SELinux策略語言之類型強制(12)

接前一篇文章:SELinux零知識學習二十六、SELinux策略語言之類型強制(11) 二、SELinux策略語言之類型強制 4. 類型規則 類型規則在創建客體或在運行過程中重新標記時指定其默認類型。在策略語言中定義了兩個類型規則: type_transtition在域轉換過程中標記行為發生時以及創…

詳解Vue中的computed和watch

詳解Vue中的computed和watch 前言原理computedcomputed特點computed有幾種創建方式應用 WatchWatch有幾種創建方式Watch主要內容Watch特性應用場景 computed和Watch區別 前言 在Vue當中,watch和computed都可以實現監聽的效果,本文主要是圍繞watch和comp…

【理解ARM架構】操作寄存器實現UART | 段的概念 | IDE背后的命令

🐱作者:一只大喵咪1201 🐱專欄:《理解ARM架構》 🔥格言:你只管努力,剩下的交給時間! 目錄 🍠操作寄存器實現UART🍟UART原理🍟編程 🍠…

python——第十二天

內置模塊或者其他模塊學習方式: dir help os模塊負責程序與操作系統的交互,提供了訪問操作系統底層的接口;即os模塊提供了非常豐富的方法用來處理文件和目錄。 os: os.path 遍歷C盤代碼 import os from os import path def …

修改YOLOv5的模型結構第三彈

🍨 本文為🔗365天深度學習訓練營 中的學習記錄博客🍖 原作者:K同學啊 | 接輔導、項目定制🚀 文章來源:K同學的學習圈子 文章目錄 任務任務拆解 開始修改C2模塊修改yolo.py修改模型配置文件 模型訓練 上次已…

【工具使用】Keil工具的使用——常用配置介紹

Keil調試具體教程學習 目錄 ???????Keil調試具體教程學習 常用功能總結 (2)目標設置(Target) ①設置晶振頻率 ②跨模塊優化選項 ③微庫選項 (3)輸出設置(Output) ①…

插入排序(形象類比)

最近在看riscv手冊的時候,里面有一段代碼是插入排序,但是單看代碼的時候有點迷,沒看懂咋操作的,后來又查資料復習了一下,最終才把代碼看明白,所以寫篇博客記錄一下。 插入排序像打撲克牌 這是我聽到過比較形…

list的總結

目錄 1.什么是list 1.1list 的優勢和劣勢 優勢: 劣勢: 2.構造函數 2.1 default (1) 2.2 fill (2) 2.3 range (3) 2.4 copy (4) 3.list iterator的使用 3.1. begin() 3.2. end() 3.3迭代器遍歷 4. list容量函數 4.1. empty() 4.2. siz…

語音合成綜述Speech Synthesis

一、語音合成概述 語音信號的產生分為兩個階段,信息編碼和生理控制。首先在大腦中出現某種想要表達的想法,然后由大腦將其編碼為具體的語言文字序列,及語音中可能存在的強調、重讀等韻律信息。經過語言的組織,大腦通過控制發音器…

正整數分解

題目編號&#xff1a;Exp08-Basic01&#xff0c;GJBook3-12-05 題目名稱&#xff1a;正整數分解 題目描述&#xff1a;正整數n&#xff0c;按第一項遞減的順序依次輸出其和等于n的所有不增的正整數和式。 輸入&#xff1a;一個正整數n&#xff08;0<n≤15&#xff09;。 …

qRT-PCR相對定量計算詳解qPCR相對定量計算方式——2^-(??Ct) deta t

做完轉錄組分析之后&#xff0c;一般都要求做qRT-PCR來驗證二代測序得到的轉錄本表達是否可靠。熒光定量PCR是一種相對表達定量的方法&#xff0c;他的計算方法有很多&#xff0c;常用的相對定量數據分析方法有雙標曲線法&#xff0c;ΔCt法&#xff0c;2^-ΔΔCt法(Livak法)&a…

順序表基本操作全面解析

文章目錄 1.線性表2.順序表分類2.1 靜態順序表2.2 動態順序表 3. 順序表各接口實現1. 定義結構體(Seqlist)2. 結構體初始化(SLInit)3.檢查容量 (SLCheckCapacity)4.打印數據 (SLPrintf)5.插入操作5.1 從數據頭部插入(SLPushFront)5.2 從數據尾部插入(SLPushBack)5.3 從任意下標…

100天精通Python(可視化篇)——第106天:Pyecharts繪制多種炫酷桑基圖參數說明+代碼實戰

文章目錄 專欄導讀一、桑基圖介紹1. 桑基圖是什么?2. 桑基圖應用場景?二、桑基圖配置選項1. 導包2. add函數3. 分層設置三、桑基圖基礎1. 普通桑基圖2. 修改標簽位置3. 修改節點布局方向4、月度開支桑基圖書籍推薦專欄導讀 ????本文已收錄于《100天精通Python從入門到就…

線性表之順序表

文章目錄 主要內容一.順序表1.插入操作&#xff1a;代碼如下&#xff08;示例&#xff09;: 2.刪除操作&#xff1a;代碼如下&#xff08;示例&#xff09;: 3.按值查找&#xff1a;代碼如下&#xff08;示例&#xff09;: 總結 主要內容 順序表 預備知識 定義&#xff1a; 線…

GEE:基于 Landst 遙感數據計算的 kNDVI 下載 APP

作者&#xff1a;CSDN _養樂多_ 本文記錄了在Google Earth Engine&#xff08;GEE&#xff09;平臺中&#xff0c;使用 Landsat 遙感數據計算并且下載 kNDVI 的應用 APP 鏈接&#xff0c;并介紹該 APP 的使用方法和步驟。該APP可以為用戶展示 NDVI 和 kNDVI 的遙感影像&#…

抽象類, 接口, Object類 ---java

目錄 一. 抽象類 1.1 抽象類概念 1.2 抽象類語法 1.3 抽象類特性 1.4 抽象類的作用 二. 接口 2.1 接口的概念 2.2 語法規則 2.3 接口的使用 2.4 接口間的繼承 2.5 抽象類和接口的區別 三. Object類 3.1 toString() 方法 3.2 對象比較equals()方法 3.3 hash…

免費獲取GPT-4的五種工具

不可否認&#xff0c;由OpenAI帶來的GPT-4已是全球最受歡迎的、功能最強大的大語言模型&#xff08;LLM&#xff09;之一。大多數人都需要使用ChatGPT Plus的訂閱服務去訪問GPT-4。為此&#xff0c;他們通常需要每月支付20美元。那么問題來了&#xff0c;如果您不想每月有這筆支…

基于JavaWeb+SpringBoot+Vue醫院管理系統小程序的設計和實現

基于JavaWebSpringBootVue醫院管理系統小程序的設計和實現 源碼獲取入口Lun文目錄前言主要技術系統設計功能截圖訂閱經典源碼專欄[Java 源碼獲取 源碼獲取入口 Lun文目錄 目錄 1系統概述 1 1.1 研究背景 1 1.2研究目的 1 1.3系統設計思想 1 2相關技術 2 2.1微信小程序 2 2.2 …

井蓋位移傳感器廠家批發,守護井蓋安全

窨井蓋廣泛分布于城市街道&#xff0c;其管理效果直接反映了城市治理的現代化程度。根據住房和城鄉建設部發布的《關于進一步加強城市窨井蓋安全管理的通知》&#xff0c;全國各地需加強窨井蓋的安全管理。作為市政基礎設施的一個重要的組成部分&#xff0c;井蓋的管理工作不僅…