久久综合九色综合97婷婷-美女视频黄频a免费-精品日本一区二区三区在线观看-日韩中文无码有码免费视频-亚洲中文字幕无码专区-扒开双腿疯狂进出爽爽爽动态照片-国产乱理伦片在线观看夜-高清极品美女毛茸茸-欧美寡妇性猛交XXX-国产亚洲精品99在线播放-日韩美女毛片又爽又大毛片,99久久久无码国产精品9,国产成a人片在线观看视频下载,欧美疯狂xxxx吞精视频

有趣生活

當(dāng)前位置:首頁>職場>技術(shù)面試中被問到怎么解決問題的(面試中經(jīng)常問到的動態(tài)代理都是什么)

技術(shù)面試中被問到怎么解決問題的(面試中經(jīng)常問到的動態(tài)代理都是什么)

發(fā)布時間:2024-01-24閱讀(14)

導(dǎo)讀動態(tài)代理動態(tài)代理有很多種方式,如jdk代理,cglib,ASM等在說動態(tài)代理之前先說一下靜態(tài)代理靜態(tài)代理靜態(tài)代理在使用時,需要定義接口或者父類,被代理對象和....

技術(shù)面試中被問到怎么解決問題的(面試中經(jīng)常問到的動態(tài)代理都是什么)(1)

動態(tài)代理

動態(tài)代理有很多種方式,如jdk代理,cglib,ASM等

在說動態(tài)代理之前先說一下靜態(tài)代理

靜態(tài)代理

靜態(tài)代理在使用時,需要定義接口或者父類,被代理對象和代理對象一起實(shí)現(xiàn)相同的接口或者繼承相同的父類

靜態(tài)代理使用的是組合模式,在代理類中包含有被代理類的對象

public class TestStaticProxy { public static void main(String[] args) { NikeClothFactory nikeClothFactory = new NikeClothFactory(); ProxyFactory proxyFactory = new ProxyFactory(nikeClothFactory); proxyFactory.productCloth(); }}// 接口interface ClothFactory{ void productCloth();}// 被代理類class NikeClothFactory implements ClothFactory{ @Override public void productCloth() { System.out.println("Nike工廠生產(chǎn)了一件Nike"); }}// 代理類class ProxyFactory implements ClothFactory{ private ClothFactory clothFactory; public ProxyFactory(ClothFactory clothFactory){ this.clothFactory = clothFactory; } @Override public void productCloth() { System.out.println("代理類開始執(zhí)行,準(zhǔn)備調(diào)用被代理類"); clothFactory.productCloth(); }}

靜態(tài)代理雖然可以在不修改目標(biāo)對象功能的前提下對目標(biāo)功能進(jìn)行擴(kuò)展,但是一旦接口增加方法,目標(biāo)對象和代理類都要同時修改,而且代理對象和被代理對象要實(shí)現(xiàn)一樣的接口,導(dǎo)致有很多的代理類,不便于維護(hù)

jdk動態(tài)代理

jdk動態(tài)代理的底層是用的是java的反射,但是jdk代理的前提是目標(biāo)類必須實(shí)現(xiàn)接口

Proxy

Proxy類是所有代理類的父類,用來生成代理類和代理對象,包含有兩個重要方法

getProxyClass方法用來生成代理類的Class

public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)

newProxyInstance方法是用來生成代理類的對象

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

使用步驟

  • 首先實(shí)現(xiàn)一個InvocationHandler,方法調(diào)用會被轉(zhuǎn)發(fā)到該類的invoke()方法
  • 調(diào)用時通過動態(tài)代理獲取代理對象

核心方法為Proxy.newProxyInstance(ClassLoader,Class[],InvocationHandler)

三個參數(shù)分別表示

  • ClassLoader 當(dāng)前目標(biāo)對象使用的類加載器
  • Class[] 目標(biāo)對象實(shí)現(xiàn)的接口類型
  • InvocationHandler 事件處理,執(zhí)行目標(biāo)對象的方法時,會觸發(fā)事件處理器的方法,會把當(dāng)前執(zhí)行目標(biāo)對象的方法作為參數(shù)傳入

public class TestDynamicProxy { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); MyInvationHandler myInvationHandler = new MyInvationHandler(); Object obj = myInvationHandler.blind(realSubject); Subject sub = (Subject) obj; sub.action(); }}// 接口interface Subject{ void action();}// 真正執(zhí)行的方法,被代理類class RealSubject implements Subject{ @Override public void action() { System.out.println("被代理類開始執(zhí)行"); }}class MyInvationHandler implements InvocationHandler{ // 實(shí)現(xiàn)了接口的被代理類的對象的聲明 Object obj; // 被代理類的實(shí)例 // 返回一個代理類的對象 public Object blind(Object obj){ this.obj = obj; // ①使用被代理類的類加載器②被代理類的接口③代理類的實(shí)例 return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this); } /** * 當(dāng)通過代理類的對象被重寫的方法調(diào)用時,都會轉(zhuǎn)換為對invoke方法的調(diào)用 * @param proxy 正在返回的代理對象,一般情況下,在invoke方法中不使用該對象 * @param method 正在被調(diào)用的方法 * @param args 調(diào)用方法時,傳入的參數(shù) * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(obj,args); }}

可以在單測方法或者main方法中添加System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");來看到代理類的class文件,文件會被生成到com/sun/proxy目錄下

cglib代理

靜態(tài)代理和jdk動態(tài)代理都要求目標(biāo)對象一定要實(shí)現(xiàn)接口,但是有時候目標(biāo)對象只是一個單獨(dú)的對象,并沒有實(shí)現(xiàn)任何接口,這個時候采用以目標(biāo)對象子類的方式實(shí)現(xiàn)代理,該方法稱為cglib代理

Cglib包的底層是通過使用一個字節(jié)碼處理框架ASM來轉(zhuǎn)換字節(jié)碼并生成新的類,由于要生成子類,所以要被代理的類不可以被final修飾

需要引入cglib的包

<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version></dependency>

使用步驟

  • 首先實(shí)現(xiàn)MethodIntercepor,方法調(diào)用會被轉(zhuǎn)發(fā)到intercept()方法
  • 使用CGLIB來獲取代理對象

public class CglibProxy implements MethodInterceptor { public Object getProxy(Class clazz){ Enhancer enhancer = new Enhancer(); // 指定代理類的父類,其實(shí)CGLIB是為該實(shí)際類生成一個子類 enhancer.setSuperclass(clazz); // 設(shè)置Callback對象 enhancer.setCallback(this); // 通過字節(jié)碼技術(shù)動態(tài)創(chuàng)建子類實(shí)例 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("前置處理"); // 調(diào)用MethodProxy.invokeSuper方法將調(diào)用轉(zhuǎn)發(fā)給原始對象 Object result = methodProxy.invokeSuper(o,objects); System.out.println("后置處理"); return result; }}public class Test { public void print(){ System.out.println("方法執(zhí)行"); } public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); Test proxyImp = (Test) proxy.getProxy(Test.class); proxyImp.print(); }}

歡迎分享轉(zhuǎn)載→http://m.avcorse.com/read-223559.html

Copyright ? 2024 有趣生活 All Rights Reserve吉ICP備19000289號-5 TXT地圖HTML地圖XML地圖