Java動(dòng)態(tài)代理的示例詳解
定義
動(dòng)態(tài)代理指的是,代理類和目標(biāo)類的關(guān)系在程序運(yùn)行的時(shí)候確定的,客戶通過(guò)代理類來(lái)調(diào)用目標(biāo)對(duì)象的方法,是在程序運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)的創(chuàng)建目標(biāo)類的代理對(duì)象。
分類
jdk動(dòng)態(tài)代理
cglib動(dòng)態(tài)代理
案例
需求
蘋果公司通過(guò)蘋果代理商來(lái)賣手機(jī)
方案一:jdk動(dòng)態(tài)代理
定義抽象接口
/**
* 售賣手機(jī)的接口(代理模式——抽象角色)
* @author:liyajie
* @createTime:2022/2/22 14:42
* @version:1.0
*/
public interface IPhone {
/**
* 出售手機(jī)
* @author: liyajie
* @date: 2022/2/22 14:44
* @param
* @return void
* @exception:
* @update:
* @updatePerson:
**/
void sellPhone();
}定義目標(biāo)類實(shí)現(xiàn)接口,重寫接口方法
/**
* 蘋果公司(代理模式——目標(biāo)角色)
* @author:liyajie
* @createTime:2022/2/22 14:46
* @version:1.0
*/
public class TargetPhone implements IPhone {
@Override
public void sellPhone() {
System.out.println("蘋果公司正在出售手機(jī)");
}
}定義代理類
/**
* 代理商(代理模式——代理角色)
* @author:liyajie
* @createTime:2022/2/22 14:50
* @version:1.0
*/
public class ProxyPhone {
private Object target;
public ProxyPhone(Object target){
this.target = target;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK動(dòng)態(tài)代理開(kāi)始之前,添加業(yè)務(wù)邏輯XXX");
//使用反射機(jī)制來(lái)調(diào)用目標(biāo)對(duì)象的方法:解決了問(wèn)題二
Object invoke = method.invoke(target, args);
System.out.println("JDK動(dòng)態(tài)代理結(jié)束之后,添加業(yè)務(wù)邏輯XXX");
return invoke;
}
});
}
}定義測(cè)試類
/**
* 測(cè)試類
* @author:liyajie
* @createTime:2022/2/23 15:15
* @version:1.0
*/
public class Test {
public static void main(String[] args) {
// 創(chuàng)建目標(biāo)類
TargetPhone targetPhone = new TargetPhone();
// 創(chuàng)建代理類
IPhone iPhone = (IPhone) new ProxyPhone(targetPhone).getProxyInstance();
System.out.println(iPhone.getClass());
// 通過(guò)代理類調(diào)用目標(biāo)方法
iPhone.sellPhone();
}
}查看測(cè)試結(jié)果

方案二:cglib動(dòng)態(tài)代理
定義目標(biāo)類
/**
* 蘋果公司(代理模式——目標(biāo)角色)
* @author:liyajie
* @createTime:2022/2/22 14:46
* @version:1.0
*/
public class TargetPhone {
public void sellPhone() {
System.out.println("蘋果公司正在出售手機(jī)");
}
}定義代理工廠,用來(lái)獲取代理類
/**
* 代理工廠
* @author:liyajie
* @createTime:2022/2/23 15:32
* @version:1.0
*/
public class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
public Object getProxyInstance(){
// 創(chuàng)建一個(gè)工具類
Enhancer enhancer = new Enhancer();
// 設(shè)置父類
enhancer.setSuperclass(target.getClass());
// 設(shè)置回調(diào)函數(shù)
enhancer.setCallback(this);
// 創(chuàng)建子類對(duì)象,即代理對(duì)象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib動(dòng)態(tài)代理開(kāi)始之前,添加業(yè)務(wù)邏輯xxxx");
Object invoke = method.invoke(target, objects);
System.out.println("cglib動(dòng)態(tài)代理之后,添加業(yè)務(wù)邏輯");
return invoke;
}
}定義測(cè)試類
/**
* 測(cè)試類
* @author:liyajie
* @createTime:2022/2/23 15:44
* @version:1.0
*/
public class Test {
public static void main(String[] args) {
// 創(chuàng)建目標(biāo)對(duì)象
TargetPhone targetPhone = new TargetPhone();
// 獲取代理對(duì)象
TargetPhone proxyInstance = (TargetPhone)new ProxyFactory(targetPhone).getProxyInstance();
// 通過(guò)代理對(duì)象調(diào)用具體的方法
proxyInstance.sellPhone();
}
}查看測(cè)試結(jié)果

分析
首先可以看到不管是jdk動(dòng)態(tài)代理,還是cglib動(dòng)態(tài)代理,實(shí)現(xiàn)的效果和靜態(tài)代理是一模一樣的,都實(shí)現(xiàn)了功能的擴(kuò)展。但是兩種動(dòng)態(tài)代理還是有些不同的,其中jdk動(dòng)態(tài)代理需要目標(biāo)對(duì)象實(shí)現(xiàn)接口,但是cglib動(dòng)態(tài)代理不需要,因?yàn)樗窃趦?nèi)存中構(gòu)建一個(gè)子類對(duì)象,從而實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象的功能擴(kuò)展。
總結(jié)
通過(guò)案例,我們了解了代理模式的幾種實(shí)現(xiàn)方式,下面我們總結(jié)下該模式:
優(yōu)勢(shì):
- 代理模式在客戶端和目標(biāo)對(duì)象之間起到了一個(gè)中介和保護(hù)的作用
- 代理對(duì)象可以對(duì)目標(biāo)對(duì)象進(jìn)行功能的擴(kuò)展和業(yè)務(wù)的擴(kuò)展,增強(qiáng)目標(biāo)對(duì)象
- 代理模式可以將客戶端和目標(biāo)對(duì)象分離,在一定程度上降低了系統(tǒng)的耦合度
劣勢(shì):
- 請(qǐng)求需要經(jīng)過(guò)代理對(duì)象,會(huì)導(dǎo)致處理速度變慢
- 因?yàn)闀?huì)有大量的代理對(duì)象產(chǎn)生,會(huì)增加系統(tǒng)的復(fù)雜度
到此這篇關(guān)于Java動(dòng)態(tài)代理的示例詳解的文章就介紹到這了,更多相關(guān)Java 動(dòng)態(tài)代理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 一文了解Java動(dòng)態(tài)代理的原理及實(shí)現(xiàn)
- Java實(shí)現(xiàn)JDK動(dòng)態(tài)代理的原理詳解
- 深入理解Java動(dòng)態(tài)代理與靜態(tài)代理
- Java實(shí)例講解動(dòng)態(tài)代理
- Java的動(dòng)態(tài)代理和靜態(tài)代理詳解
- Java?靜態(tài)代理與動(dòng)態(tài)代理解析
- 帶你重新認(rèn)識(shí)Java動(dòng)態(tài)代理
- Java實(shí)現(xiàn)動(dòng)態(tài)代理的實(shí)例代碼
- Java深入分析動(dòng)態(tài)代理
相關(guān)文章
vue3實(shí)現(xiàn)一個(gè)todo-list
這篇文章主要為大家詳細(xì)介紹了基于vuejs實(shí)現(xiàn)一個(gè)todolist項(xiàng)目,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來(lái)幫助2021-08-08
SpringMVC中RequestContextHolder獲取請(qǐng)求信息的方法
這篇文章主要介紹了SpringMVC中RequestContextHolder獲取請(qǐng)求信息的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Java實(shí)戰(zhàn)之醫(yī)院管理系統(tǒng)的實(shí)現(xiàn)
這篇文章主要介紹了如何利用Java實(shí)現(xiàn)醫(yī)院管理系統(tǒng),文中用到的技術(shù)有:SpringBoot、Layui、Freemaker等,感興趣的同學(xué)可以了解一下2022-04-04
MyBatis?Plus如何實(shí)現(xiàn)獲取自動(dòng)生成主鍵值
這篇文章主要介紹了MyBatis?Plus如何實(shí)現(xiàn)獲取自動(dòng)生成主鍵值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
spring配置定時(shí)任務(wù)的幾種方式總結(jié)
這篇文章主要介紹了spring配置定時(shí)任務(wù)的幾種方式總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
java+jsp+struts2實(shí)現(xiàn)發(fā)送郵件功能
這篇文章主要為大家詳細(xì)介紹了java+jsp+struts2實(shí)現(xiàn)發(fā)送郵件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
關(guān)于Hadoop中Spark?Streaming的基本概念
這篇文章主要介紹了關(guān)于Hadoop中Spark?Streaming的基本概念,Spark?Streaming是構(gòu)建在Spark上的實(shí)時(shí)計(jì)算框架,它擴(kuò)展了Spark處理大規(guī)模流式數(shù)據(jù)的能力,Spark?Streaming可結(jié)合批處理和交互式查詢,需要的朋友可以參考下2023-07-07
Java工具之ja-netfilter?2022.1?配置教程
這篇文章主要介紹了Java工具之ja-netfilter?2022.1?配置教程,本防火墻基于javaagent,所以目前只有基于java的程序能夠使用,需要的朋友可以參考下2022-04-04

