Java動態(tài)代理的示例詳解
定義
動態(tài)代理指的是,代理類和目標(biāo)類的關(guān)系在程序運(yùn)行的時候確定的,客戶通過代理類來調(diào)用目標(biāo)對象的方法,是在程序運(yùn)行時根據(jù)需要動態(tài)的創(chuàng)建目標(biāo)類的代理對象。
分類
jdk動態(tài)代理
cglib動態(tài)代理
案例
需求
蘋果公司通過蘋果代理商來賣手機(jī)
方案一:jdk動態(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動態(tài)代理開始之前,添加業(yè)務(wù)邏輯XXX");
//使用反射機(jī)制來調(diào)用目標(biāo)對象的方法:解決了問題二
Object invoke = method.invoke(target, args);
System.out.println("JDK動態(tài)代理結(jié)束之后,添加業(yè)務(wù)邏輯XXX");
return invoke;
}
});
}
}定義測試類
/**
* 測試類
* @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());
// 通過代理類調(diào)用目標(biāo)方法
iPhone.sellPhone();
}
}查看測試結(jié)果

方案二:cglib動態(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ī)");
}
}定義代理工廠,用來獲取代理類
/**
* 代理工廠
* @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)建一個工具類
Enhancer enhancer = new Enhancer();
// 設(shè)置父類
enhancer.setSuperclass(target.getClass());
// 設(shè)置回調(diào)函數(shù)
enhancer.setCallback(this);
// 創(chuàng)建子類對象,即代理對象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib動態(tài)代理開始之前,添加業(yè)務(wù)邏輯xxxx");
Object invoke = method.invoke(target, objects);
System.out.println("cglib動態(tài)代理之后,添加業(yè)務(wù)邏輯");
return invoke;
}
}定義測試類
/**
* 測試類
* @author:liyajie
* @createTime:2022/2/23 15:44
* @version:1.0
*/
public class Test {
public static void main(String[] args) {
// 創(chuàng)建目標(biāo)對象
TargetPhone targetPhone = new TargetPhone();
// 獲取代理對象
TargetPhone proxyInstance = (TargetPhone)new ProxyFactory(targetPhone).getProxyInstance();
// 通過代理對象調(diào)用具體的方法
proxyInstance.sellPhone();
}
}查看測試結(jié)果

分析
首先可以看到不管是jdk動態(tài)代理,還是cglib動態(tài)代理,實(shí)現(xiàn)的效果和靜態(tài)代理是一模一樣的,都實(shí)現(xiàn)了功能的擴(kuò)展。但是兩種動態(tài)代理還是有些不同的,其中jdk動態(tài)代理需要目標(biāo)對象實(shí)現(xiàn)接口,但是cglib動態(tài)代理不需要,因?yàn)樗窃趦?nèi)存中構(gòu)建一個子類對象,從而實(shí)現(xiàn)對目標(biāo)對象的功能擴(kuò)展。
總結(jié)
通過案例,我們了解了代理模式的幾種實(shí)現(xiàn)方式,下面我們總結(jié)下該模式:
優(yōu)勢:
- 代理模式在客戶端和目標(biāo)對象之間起到了一個中介和保護(hù)的作用
- 代理對象可以對目標(biāo)對象進(jìn)行功能的擴(kuò)展和業(yè)務(wù)的擴(kuò)展,增強(qiáng)目標(biāo)對象
- 代理模式可以將客戶端和目標(biāo)對象分離,在一定程度上降低了系統(tǒng)的耦合度
劣勢:
- 請求需要經(jīng)過代理對象,會導(dǎo)致處理速度變慢
- 因?yàn)闀写罅康拇韺ο螽a(chǎn)生,會增加系統(tǒng)的復(fù)雜度
到此這篇關(guān)于Java動態(tài)代理的示例詳解的文章就介紹到這了,更多相關(guān)Java 動態(tài)代理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java操作MongoDB數(shù)據(jù)庫的示例代碼
這篇文章主要介紹了Java操作MongoDB的示例代碼,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-04-04
SpringBoot實(shí)現(xiàn)評論回復(fù)功能(數(shù)據(jù)庫設(shè)計)
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)評論回復(fù)功能(數(shù)據(jù)庫設(shè)計),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04
Mybatis之@ResultMap,@Results,@Result注解的使用
這篇文章主要介紹了Mybatis之@ResultMap,@Results,@Result注解的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
基于java socket實(shí)現(xiàn) 聊天小程序
這篇文章主要介紹了基于java socket實(shí)現(xiàn) 聊天小程序,代碼分為服務(wù)器和客戶端,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12
手把手帶你分析SpringBoot自動裝配完成了Ribbon哪些核心操作
這篇文章主要介紹了詳解Spring Boot自動裝配Ribbon哪些核心操作的哪些操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08

