最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Java動態(tài)代理怎么實現(xiàn)的?

2023-07-07 13:11 作者:技術(shù)至上  | 我要投稿

如題,這個問題應(yīng)該面試長考題,當你遇到這個問題時,如果你能回答出來JDK動態(tài)代理的原理,然后引申Cglib 動態(tài)代理,那么這個面試官一定會對你刮目相看。

在Java中,動態(tài)代理是一種機制,允許在運行時動態(tài)地創(chuàng)建代理對象來代替某個實際對象,從而在其前后執(zhí)行額外的邏輯。

為什么JDK動態(tài)代理只能代理接口實現(xiàn)類,原因是JDK動態(tài)代理是基于接口實現(xiàn)的。

當你使用Proxy類創(chuàng)建代理對象時,你需要指定一個接口列表來表示代理對象所應(yīng)該實現(xiàn)的接口,這些接口就成為代理對象的類型。

具體來說,代理對象的方法調(diào)用會被轉(zhuǎn)發(fā)到實現(xiàn)InvocationHandler接口的類中的invoke()方法。這個invoke()方法接受三個參數(shù):代理對象本身、被調(diào)用的方法對象和方法的參數(shù)數(shù)組。invoke()方法需要返回被代理方法調(diào)用的結(jié)果。

由于代理對象的類型是由接口列表決定的,因此只有實現(xiàn)了接口的類才能被代理。如果你想代理一個類而不是一個接口,你需要使用其他的代理技術(shù),比如CGLIB。

1、JDK動態(tài)代理代碼實例

下面是一個簡單的示例代碼,展示了如何使用JDK動態(tài)代理來創(chuàng)建代理對象。

import?java.lang.reflect.InvocationHandler;
import?java.lang.reflect.Method;
import?java.lang.reflect.Proxy;

public?class?ProxyDemo?{
????public?static?void?main(String[]?args)?{
????????RealObject?real?=?new?RealObject();
????????InvocationHandler?handler?=?new?DynamicProxy(real);

????????//?創(chuàng)建代理對象
????????MyInterface?proxy?=?(MyInterface)?Proxy.newProxyInstance(
????????????????MyInterface.class.getClassLoader(),
????????????????new?Class<?>[]?
{?MyInterface.class?},
????????????????handler)
;

????????//?調(diào)用代理對象的方法
????????proxy.doSomething();
????}
}

interface?MyInterface?{
????void?doSomething();
}

class?RealObject?implements?MyInterface?{
????public?void?doSomething()?{
????????System.out.println("RealObject?doSomething");
????}
}

class?DynamicProxy?implements?InvocationHandler?{
????private?Object?target;

????public?DynamicProxy(Object?target)?{
????????this.target?=?target;
????}

????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)
????????????throws?Throwable?
{
????????System.out.println("Before?method?invocation");
????????Object?result?=?method.invoke(target,?args);
????????System.out.println("After?method?invocation");
????????return?result;
????}
}

在上面的代碼中,RealObject實現(xiàn)了MyInterface接口,它是我們要代理的實際對象。DynamicProxy類實現(xiàn)了InvocationHandler接口,并在invoke()方法中添加了額外的邏輯,用于在代理對象方法調(diào)用前后執(zhí)行。

main()方法中,我們使用Proxy.newProxyInstance()方法創(chuàng)建代理對象。我們指定了MyInterface接口作為代理對象類型,并將DynamicProxy對象作為代理對象的InvocationHandler。

最后,我們調(diào)用代理對象的doSomething()方法,并觀察控制臺輸出的結(jié)果。

需要注意的是,代理對象的方法調(diào)用都會被轉(zhuǎn)發(fā)到DynamicProxy類的invoke()方法中進行處理,因此在這個示例中,實際的RealObject對象的doSomething()方法的執(zhí)行是在invoke()方法中通過反射進行的。

總結(jié)一下,JDK動態(tài)代理只能代理接口實現(xiàn)類,原因是JDK動態(tài)代理是基于接口實現(xiàn)的,代理對象的類型由接口列表決定。如果你想代理一個類而不是一個接口,你需要使用其他的代理技術(shù),比如CGLIB。

2、Cglib 代碼演示

以下是CGLIB代理的示例代碼。

import?net.sf.cglib.proxy.Enhancer;
import?net.sf.cglib.proxy.MethodInterceptor;
import?net.sf.cglib.proxy.MethodProxy;

import?java.lang.reflect.Method;

public?class?CGLIBProxyDemo?{
????public?static?void?main(String[]?args)?{
????????RealObject?real?=?new?RealObject();
????????MethodInterceptor?handler?=?new?CGLIBProxy(real);

????????//?創(chuàng)建代理對象
????????RealObject?proxy?=?(RealObject)?Enhancer.create(
????????????????RealObject.class,
????????????????handler)
;

????????//?調(diào)用代理對象的方法
????????proxy.doSomething();
????}
}

class?CGLIBProxy?implements?MethodInterceptor?{
????private?Object?target;

????public?CGLIBProxy(Object?target)?{
????????this.target?=?target;
????}

????public?Object?intercept(Object?obj,?Method?method,?Object[]?args,?MethodProxy?proxy)?throws?Throwable?{
????????System.out.println("Before?method?invocation");
????????Object?result?=?proxy.invoke(target,?args);
????????System.out.println("After?method?invocation");
????????return?result;
????}
}

在上面的示例中,我們使用CGLIB的Enhancer類和MethodInterceptor接口來創(chuàng)建代理對象。RealObject類不再需要實現(xiàn)接口,而是直接作為代理對象的類型。在CGLIBProxy類中,我們實現(xiàn)了MethodInterceptor接口,并在intercept()方法中添加了額外的邏輯。

main()方法中,我們使用Enhancer.create()方法創(chuàng)建代理對象。我們指定了RealObject類作為代理對象類型,并將CGLIBProxy對象作為代理對象的MethodInterceptor。最后,我們調(diào)用代理對象的doSomething()方法,并觀察控制臺輸出的結(jié)果。

需要注意的是,CGLIB代理使用字節(jié)碼技術(shù)來生成代理對象,因此它的效率比JDK動態(tài)代理要高,但是它也需要額外的庫依賴。

3、兩者優(yōu)缺點

JDK動態(tài)代理和CGLIB代理都有它們自己的優(yōu)缺點。

JDK動態(tài)代理的優(yōu)點:

  • JDK動態(tài)代理是Java標準庫的一部分,因此它不需要引入任何外部依賴。

  • JDK動態(tài)代理只需要實現(xiàn)接口即可生成代理對象,不需要改變原有類的結(jié)構(gòu)。

  • 由于JDK動態(tài)代理是基于接口實現(xiàn)的,因此它更適合用于代理接口實現(xiàn)類的場景。

JDK動態(tài)代理的缺點:

  • JDK動態(tài)代理只能代理實現(xiàn)了接口的類,無法代理沒有實現(xiàn)接口的類。

  • JDK動態(tài)代理在生成代理對象時,需要使用反射機制,因此它的效率相對較低。

CGLIB代理的優(yōu)點:

  • CGLIB代理是基于字節(jié)碼技術(shù)實現(xiàn)的,因此它的效率比JDK動態(tài)代理更高。

  • CGLIB代理可以代理沒有實現(xiàn)接口的類。

CGLIB代理的缺點:

  • CGLIB代理需要引入外部依賴。

  • CGLIB代理在生成代理對象時,需要改變原有類的結(jié)構(gòu),因此它可能會引起一些問題,例如無法代理final類或final方法等問題。

綜上所述,JDK動態(tài)代理適用于代理接口實現(xiàn)類的場景,而CGLIB代理適用于代理沒有實現(xiàn)接口的類的場景。如果你需要代理接口實現(xiàn)類,而且不想引入額外的依賴,那么JDK動態(tài)代理是一個不錯的選擇;如果你需要代理沒有實現(xiàn)接口的類,那么CGLIB代理可能更適合你的需求。


Java動態(tài)代理怎么實現(xiàn)的?的評論 (共 條)

分享到微博請遵守國家法律
阜南县| 青岛市| 克山县| 靖西县| 弥勒县| 渑池县| 军事| 宝山区| 读书| 崇文区| 扶绥县| 天镇县| 彭州市| 凌海市| 临海市| 呼玛县| 南川市| 博罗县| 贵港市| 鞍山市| 磐安县| 双柏县| 池州市| 奉节县| 新和县| 宜州市| 尼木县| 米易县| 镇安县| 清丰县| 申扎县| 马山县| 沁水县| 井陉县| 恩平市| 雷山县| 新昌县| 禄劝| 仪征市| 周宁县| 策勒县|