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

動態(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)接口
ProxyProxy類是所有代理類的父類,用來生成代理類和代理對象,包含有兩個重要方法
getProxyClass方法用來生成代理類的Class
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
newProxyInstance方法是用來生成代理類的對象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
使用步驟
核心方法為Proxy.newProxyInstance(ClassLoader,Class[],InvocationHandler)
三個參數(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地圖