RE|GoF23种设计模式-动态代理
生活随笔
收集整理的這篇文章主要介紹了
RE|GoF23种设计模式-动态代理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
代理模式
定義
代理(Proxy)是一種設計模式,提供了對目標對象另外的訪問方式;即通過代理對象訪問目標對象.這樣做的好處是:可以在目標對象實現的基礎上,增強額外的功能操作,即擴展目標對象的功能。符合開閉原則。代理模式屬于結構型 模式,有靜態代理和動態代理。
靜態代理
需求:現在我們需要根據類型來分別把數據上傳到不同Ftp服務。
/*** 數據的模型類*/ public static class Data {private Integer type;private String name;private String sex;public Integer getType() {return type;}public void setType(Integer type) {this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}}public static interface IFTPService {void upload(Data data); }public static class FTPService implements IFTPService {public void upload(Data data) {System.out.println("Data{" +"type=" + data.getType() +", name='" + data.getName() + '\'' +", sex='" + data.getSex() + '\'' +'}');}}public static class FTPServiceStaticProxy implements IFTPService {private IFTPService ftpService;// 靜態代理 構造注入的方式賦值public FTPServiceStaticProxy(IFTPService ftpService) {this.ftpService = ftpService;}public void upload(Data data) {before();if (data.getType() % 2 == 0) {System.out.println("上傳到服務器 1");ftpService.upload(data);} else {System.out.println("上傳到服務器 2");ftpService.upload(data);}after();}private void before(){System.out.println("Proxy before method.");}private void after(){System.out.println("Proxy after method.");} }public static void main(String[] args) {Data data = new Data();data.setName("Name Zhuang San");data.setSex("男");data.setType(1);new FTPServiceStaticProxy(new FTPService()).upload(data);Data data2 = new Data();data.setName("Name Wan Wu");data.setSex("男");data.setType(2);new FTPServiceStaticProxy(new FTPService()).upload(data); }復制代碼動態代理
動態代理有以下特點:
JDK 實現方式
/*** 數據的模型類*/ public static class Data {private Integer type;private String name;private String sex;public Integer getType() {return type;}public void setType(Integer type) {this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}}public static interface IFTPService {void upload(Data data); }public static class FTPService implements IFTPService {public void upload(Data data) {System.out.println("Data{" +"type=" + data.getType() +", name='" + data.getName() + '\'' +", sex='" + data.getSex() + '\'' +'}');}}public static class JDKProxyFTPService implements InvocationHandler {private Object target;public Object upload(Object target) {this.target = target;Class<?> clazz = target.getClass();// 如何實現的代理?return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 只讓 upload 方法進入if (!"upload".equals(method.getName())) return method.invoke(target, args);before(args[0]);Object r = method.invoke(target, args);after();return r;}private void before(Object data){System.out.println("Proxy before method.");if (data instanceof Data) { // 判斷是否屬于 -- Data 模型Data d = (Data) data;if (d.getType() % 2 == 0)System.out.println("上傳到服務器 1");elseSystem.out.println("上傳到服務器 2");}}private void after(){System.out.println("Proxy after method.");}}public static void main(String[] args) {IFTPService ftpService = (IFTPService) new JDKProxyFTPService().upload(new FTPService());Data data = new Data();data.setName("Name Zhuang San");data.setSex("男");data.setType(1);ftpService.upload(data); }復制代碼Proxy 是如何實現的呢?
我們都知道 JDK Proxy 采用字節重組,重新生的對象來替代原始的對象以達到動態代理的目的。JDK Proxy 生成對象的步驟如下:
使用反編譯工具,得到java代碼如下:
package com.reape.design.pattern.proxy;import java.lang.reflect.*; import com.reape.design.pattern.proxy.*;// 繼承了Proxy類 接口我們的 JDKIFTPService public final class $Proxy0 extends Proxy implements JDKIFTPService {private static Method m1;private static Method m3;private static Method m2;private static Method m0;public $Proxy0(final InvocationHandler invocationHandler) {super(invocationHandler);}// 重寫了 toString hashCode equals 指向了原來的地址public final boolean equals(final Object o) {try {return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });}catch (Error | RuntimeException error) {throw new Error();}catch (Throwable t) {throw new UndeclaredThrowableException(t);}}public final void upload(final JDKData jdkData) {try {super.h.invoke(this, $Proxy0.m3, new Object[] { jdkData });}catch (Error | RuntimeException error) {throw new Error();}catch (Throwable t) {throw new UndeclaredThrowableException(t);}}public final String toString() {try {return (String)super.h.invoke(this, $Proxy0.m2, null);}catch (Error | RuntimeException error) {throw new Error();}catch (Throwable t) {throw new UndeclaredThrowableException(t);}}public final int hashCode() {try {return (int)super.h.invoke(this, $Proxy0.m0, null);}catch (Error | RuntimeException error) {throw new Error();}catch (Throwable t) {throw new UndeclaredThrowableException(t);}}static {try {$Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));$Proxy0.m3 = Class.forName("com.reape.design.pattern.proxy.JDKIFTPService").getMethod("upload", Class.forName("com.reape.design.pattern.proxy.JDKData"));$Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);$Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);}catch (NoSuchMethodException ex) {throw new NoSuchMethodError(ex.getMessage());}catch (ClassNotFoundException ex2) {throw new NoClassDefFoundError(ex2.getMessage());}} }復制代碼手寫動態代理
// 1. ClassLoader 自定義import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException;public class MyClassLoader extends ClassLoader{private File classPathFile;public MyClassLoader(){String classPath = MyClassLoader.class.getResource("").getPath();this.classPathFile = new File(classPath);}protected Class<?> findClass(String name) throws ClassNotFoundException {String className = MyClassLoader.class.getPackage().getName() + "." + name;if(classPathFile != null){File classFile = new File(classPathFile,name.replaceAll("\\.","/") + ".class");if(classFile.exists()){FileInputStream in = null;ByteArrayOutputStream out = null;try{in = new FileInputStream(classFile);out = new ByteArrayOutputStream();byte [] buff = new byte[1024];int len;while ((len = in.read(buff)) != -1){out.write(buff,0,len);}return defineClass(className,out.toByteArray(),0,out.size());}catch (Exception e){e.printStackTrace();}finally {if(null != in){try {in.close();} catch (IOException e) {e.printStackTrace();}}if(out != null){try {out.close();} catch (IOException e) {e.printStackTrace();}}}}}return null;} }// 2. 動態代理實現的接口類 import java.lang.reflect.Method;/*** 動態代理實現的接口類*/ public interface MyInvocationHandler {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;}3. 生成java文件編譯為class寫入jvm,動態代理/*** 用來生成源代碼的工具類*/ public class MyProxy {private static final String ln = "\r\n";private static final String t = "\t";public static Object newProxyInstance(MyClassLoader classLoader,Class<?> [] interfaces,MyInvocationHandler h){try {// 1.動態生成源代碼文件String src = generateSrc(interfaces);//2、Java 文件輸出磁盤String filePath = MyProxy.class.getResource("").getPath();System.out.println(filePath);File f = new File(filePath + "$Proxy0.java");FileWriter fw = null;fw = new FileWriter(f);fw.write(src);fw.flush();fw.close();//3、把生成的.java 文件編譯成.class 文件JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager manage = compiler.getStandardFileManager(null,null,null);Iterable iterable = manage.getJavaFileObjects(f);JavaCompiler.CompilationTask task =compiler.getTask(null,manage,null,null,null, iterable);task.call();manage.close();//4、編譯生成的.class 文件加載到 JVM 中來Class<Object> proxyClass = (Class<Object>) classLoader.findClass("$Proxy0");Constructor<Object> c = proxyClass.getConstructor(MyInvocationHandler.class); // f.delete();//5、返回字節碼重組以后的新的代理對象return c.newInstance(h);} catch (IOException | InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {e.printStackTrace();}return null;}private static String generateSrc(Class<?>[] interfaces){// interfaces ---> 需要實現的接口的類StringBuilder sb = new StringBuilder();sb.append("package com.reape.design.pattern.proxy.handwriting;" + ln);sb.append("import java.lang.reflect.*;" + ln);sb.append("public class $Proxy0 implements").append(interfacesToString(interfaces));sb.append(" {").append(ln);sb.append(t + "private com.reape.design.pattern.proxy.handwriting.MyInvocationHandler h;" + ln);sb.append(t + "public $Proxy0(com.reape.design.pattern.proxy.handwriting.MyInvocationHandler h) { " + ln);sb.append(t + t + "this.h = h;" + ln);sb.append(t + "}" + ln);for (Class<?> anInterface : interfaces) {for (Method m : anInterface.getMethods()) {Class<?>[] params = m.getParameterTypes();Class<?> result = m.getReturnType();sb.append(t + "public final ").append(resultToString(result)).append(" ").append(m.getName()).append("(").append(paramsToString(params)).append(") {").append(ln);sb.append(t + t + "try {" + ln);sb.append(t + t + t).append(returnToString(result)).append("h.invoke(this, " + "Class.forName(\"") // .append(anInterface.getName()).append("com.reape.design.pattern.proxy.JDKFTPService").append("\")").append(".getMethod(").append("\"").append(m.getName()).append("\"").append(", ").append(paramsFormNameToString(params)).append(")").append(", new Object[]{ p0 });").append(ln);sb.append(t + t + "}" + ln);sb.append(t + t + "catch(Error | RuntimeException error) { error.printStackTrace();" + ln);sb.append(t + t + t + "throw new Error();" + ln);sb.append(t + t + "}" + ln);sb.append(t + t + "catch (Throwable t) {" + ln);sb.append(t + t + t + "throw new UndeclaredThrowableException(t);" + ln);sb.append(t + t + "}" + ln);sb.append(t + "}" + ln);}}sb.append("}" + ln);return sb.toString();}/*** 接口類數組轉 String* @param interfaces 接口類數組* @return 字符串*/private static String interfacesToString(Class<?>[] interfaces) {if (interfaces.length < 1) return "";StringBuilder sb = new StringBuilder();for (Class<?> anInterface : interfaces) {sb.append(" ").append(anInterface.getName()).append(",");}return sb.substring(0, sb.length() - 1);}private static String paramsToString(Class<?>[] params) {if (params.length < 1) return "";StringBuilder sb = new StringBuilder();for (int i = 0; i < params.length; i++) {sb.append(params[i].getName()).append(" ").append("p").append(i).append(", ");}return sb.substring(0, sb.length() - 2);}private static String paramsFormNameToString(Class<?>[] params) {if (params.length < 1) return "";StringBuilder sb = new StringBuilder();for (Class<?> param : params) {sb.append("Class.forName(\"").append(param.getName()).append("\"), ");}return sb.substring(0, sb.length() - 2);}private static String resultToString(Class<?> result) {String name = result.getName();return "void".equals(name) ? "void" : name;}private static String returnToString(Class<?> result) {String name = result.getName();return "void".equals(name) ? "" : "return (" + name + ") ";}}// 4.測試public class Test implements MyInvocationHandler {private Object target;public Object get(Object target) {this.target = target;Class<?> clazz = target.getClass();return MyProxy.newProxyInstance(new MyClassLoader(), clazz.getInterfaces(), this);}private void before(Object data){System.out.println(data);System.out.println("Proxy before method.");}private void after(){System.out.println("Proxy after method.");}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 只讓 upload 方法進入if (!"upload".equals(method.getName())) return method.invoke(target, args);before(args[0]);Object r = method.invoke(target, args);after();return r;}public static void main(String[] args) {JDKIFTPService ftpService = (JDKIFTPService) new Test().get(new JDKFTPService());JDKData data = new JDKData();data.setName("Name Zhuang San");data.setSex("男");data.setType(1);ftpService.upload(data);}}// 上面的代碼寫考慮的不是很完整 // 有很多判斷的地方沒有判斷以及重寫 toString ,equals 等// java的代理是編譯為class文件然后寫入的到jvm節約的了內存消耗,但是跟cglib對比還是差很遠 // cglib是字節碼操作復制代碼CGLib實現
// 導入jar包 // 1. asm.jar // 2. cglib.jarpublic class JDKData {private Integer type;private String name;private String sex;public Integer getType() {return type;}public void setType(Integer type) {this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;} }public class JDKFTPService implements JDKIFTPService {public void upload(JDKData data) {System.out.println("Data{" +"type=" + data.getType() +", name='" + data.getName() + '\'' +", sex='" + data.getSex() + '\'' +'}');} }public class CglibJDK implements MethodInterceptor {public Object getInstance(Class<?> clazz) throws Exception{Enhancer enhancer = new Enhancer();//要把哪個設置為即將生成的新類父類enhancer.setSuperclass(clazz);enhancer.setCallback(this);return enhancer.create();}public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {//業務的增強before(objects[0]);Object obj = methodProxy.invokeSuper(o,objects);after();return obj;}private void before(Object data){System.out.println("Proxy before method.");System.out.println(data);if (data instanceof JDKData) { // 判斷是否屬于 -- Data 模型JDKData d = (JDKData) data;if (d.getType() % 2 == 0)System.out.println("上傳到服務器 1");elseSystem.out.println("上傳到服務器 2");}}private void after(){System.out.println("Proxy after method.");} }// 測試 public static void main(String[] args) {try {JDKFTPService obj = (JDKFTPService) new CglibJDK().getInstance(JDKFTPService.class);JDKData data = new JDKData();data.setName("Name Zhuang San");data.setSex("男");data.setType(1);obj.upload(data);} catch (Exception e) {e.printStackTrace();} }// 編譯得到class文件package com.reape.design.pattern.proxy.cglib;import net.sf.cglib.reflect.*; import net.sf.cglib.core.*; import net.sf.cglib.proxy.*; import java.lang.reflect.*;public class JDKFTPService$$EnhancerByCGLIB$$5a7831ef$$FastClassByCGLIB$$5a694231 extends FastClass {public JDKFTPService$$EnhancerByCGLIB$$5a7831ef$$FastClassByCGLIB$$5a694231(final Class clazz) {super(clazz);}public int getIndex(final Signature signature) {final String string = signature.toString();switch (string.hashCode()) {case -2055565910: {if (string.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {return 12;}break;}case -1882565338: {if (string.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {return 15;}break;}case -1457535688: {if (string.equals("CGLIB$STATICHOOK1()V")) {return 19;}break;}case -1411842725: {if (string.equals("CGLIB$hashCode$3()I")) {return 18;}break;}case -894172689: {if (string.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 6;}break;}case -623122092: {if (string.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {return 20;}break;}case -508378822: {if (string.equals("clone()Ljava/lang/Object;")) {return 3;}break;}case -419626537: {if (string.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {return 11;}break;}case 560567118: {if (string.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {return 7;}break;}case 773140094: {if (string.equals("CGLIB$upload$0(Lcom/reape/design/pattern/proxy/cglib/JDKData;)V")) {return 14;}break;}case 811063227: {if (string.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 5;}break;}case 840180909: {if (string.equals("upload(Lcom/reape/design/pattern/proxy/cglib/JDKData;)V")) {return 8;}break;}case 973717575: {if (string.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {return 10;}break;}case 1221173700: {if (string.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {return 4;}break;}case 1230699260: {if (string.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {return 9;}break;}case 1306468936: {if (string.equals("CGLIB$toString$2()Ljava/lang/String;")) {return 16;}break;}case 1584330438: {if (string.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {return 13;}break;}case 1800494055: {if (string.equals("CGLIB$clone$4()Ljava/lang/Object;")) {return 17;}break;}case 1826985398: {if (string.equals("equals(Ljava/lang/Object;)Z")) {return 0;}break;}case 1913648695: {if (string.equals("toString()Ljava/lang/String;")) {return 1;}break;}case 1984935277: {if (string.equals("hashCode()I")) {return 2;}break;}}return -1;}public int getIndex(final String s, final Class[] array) {Label_1103: {switch (s.hashCode()) {case -1776922004: {if (!s.equals("toString")) {break;}switch (array.length) {case 0: {return 1;}default: {break Label_1103;}}break;}case -1295482945: {if (!s.equals("equals")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("java.lang.Object")) {return 0;}break Label_1103;}default: {break Label_1103;}}break;}case -1053468136: {if (!s.equals("getCallbacks")) {break;}switch (array.length) {case 0: {return 10;}default: {break Label_1103;}}break;}case -838595071: {if (!s.equals("upload")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("com.reape.design.pattern.proxy.cglib.JDKData")) {return 8;}break Label_1103;}default: {break Label_1103;}}break;}case -124978609: {if (!s.equals("CGLIB$equals$1")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("java.lang.Object")) {return 15;}break Label_1103;}default: {break Label_1103;}}break;}case -60403779: {if (!s.equals("CGLIB$SET_STATIC_CALLBACKS")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {return 13;}break Label_1103;}default: {break Label_1103;}}break;}case -29025555: {if (!s.equals("CGLIB$hashCode$3")) {break;}switch (array.length) {case 0: {return 18;}default: {break Label_1103;}}break;}case 85179481: {if (!s.equals("CGLIB$SET_THREAD_CALLBACKS")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {return 12;}break Label_1103;}default: {break Label_1103;}}break;}case 94756189: {if (!s.equals("clone")) {break;}switch (array.length) {case 0: {return 3;}default: {break Label_1103;}}break;}case 147696667: {if (!s.equals("hashCode")) {break;}switch (array.length) {case 0: {return 2;}default: {break Label_1103;}}break;}case 161998109: {if (!s.equals("CGLIB$STATICHOOK1")) {break;}switch (array.length) {case 0: {return 19;}default: {break Label_1103;}}break;}case 495524492: {if (!s.equals("setCallbacks")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {return 11;}break Label_1103;}default: {break Label_1103;}}break;}case 857604112: {if (!s.equals("CGLIB$upload$0")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("com.reape.design.pattern.proxy.cglib.JDKData")) {return 14;}break Label_1103;}default: {break Label_1103;}}break;}case 1154623345: {if (!s.equals("CGLIB$findMethodProxy")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("net.sf.cglib.core.Signature")) {return 20;}break Label_1103;}default: {break Label_1103;}}break;}case 1543336189: {if (!s.equals("CGLIB$toString$2")) {break;}switch (array.length) {case 0: {return 16;}default: {break Label_1103;}}break;}case 1811874389: {if (!s.equals("newInstance")) {break;}switch (array.length) {case 1: {final String name = array[0].getName();switch (name.hashCode()) {case -845341380: {if (name.equals("net.sf.cglib.proxy.Callback")) {return 6;}break;}case 1730110032: {if (name.equals("[Lnet.sf.cglib.proxy.Callback;")) {return 4;}break;}}break Label_1103;}case 3: {if (array[0].getName().equals("[Ljava.lang.Class;") && array[1].getName().equals("[Ljava.lang.Object;") && array[2].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {return 5;}break Label_1103;}default: {break Label_1103;}}break;}case 1817099975: {if (!s.equals("setCallback")) {break;}switch (array.length) {case 2: {if (array[0].getName().equals("int") && array[1].getName().equals("net.sf.cglib.proxy.Callback")) {return 7;}break Label_1103;}default: {break Label_1103;}}break;}case 1905679803: {if (!s.equals("getCallback")) {break;}switch (array.length) {case 1: {if (array[0].getName().equals("int")) {return 9;}break Label_1103;}default: {break Label_1103;}}break;}case 1951977610: {if (!s.equals("CGLIB$clone$4")) {break;}switch (array.length) {case 0: {return 17;}default: {break Label_1103;}}break;}}}return -1;}public int getIndex(final Class[] array) {switch (array.length) {case 0: {return 0;}default: {return -1;}}}public Object invoke(final int n, final Object o, final Object[] array) throws InvocationTargetException {final JDKFTPService$$EnhancerByCGLIB$$5a7831ef jdkftpService$$EnhancerByCGLIB$$5a7831ef = (JDKFTPService$$EnhancerByCGLIB$$5a7831ef)o;try {switch (n) {case 0: {return new Boolean(jdkftpService$$EnhancerByCGLIB$$5a7831ef.equals(array[0]));}case 1: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.toString();}case 2: {return new Integer(jdkftpService$$EnhancerByCGLIB$$5a7831ef.hashCode());}case 3: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.clone();}case 4: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Callback[])array[0]);}case 5: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Class[])array[0], (Object[])array[1], (Callback[])array[2]);}case 6: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Callback)array[0]);}case 7: {jdkftpService$$EnhancerByCGLIB$$5a7831ef.setCallback(((Number)array[0]).intValue(), (Callback)array[1]);return null;}case 8: {jdkftpService$$EnhancerByCGLIB$$5a7831ef.upload((JDKData)array[0]);return null;}case 9: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.getCallback(((Number)array[0]).intValue());}case 10: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.getCallbacks();}case 11: {jdkftpService$$EnhancerByCGLIB$$5a7831ef.setCallbacks((Callback[])array[0]);return null;}case 12: {JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$SET_THREAD_CALLBACKS((Callback[])array[0]);return null;}case 13: {JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$SET_STATIC_CALLBACKS((Callback[])array[0]);return null;}case 14: {jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$upload$0((JDKData)array[0]);return null;}case 15: {return new Boolean(jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$equals$1(array[0]));}case 16: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$toString$2();}case 17: {return jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$clone$4();}case 18: {return new Integer(jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$hashCode$3());}case 19: {JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$STATICHOOK1();return null;}case 20: {return JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$findMethodProxy((Signature)array[0]);}}}catch (Throwable t) {throw new InvocationTargetException(t);}throw new IllegalArgumentException("Cannot find matching method/constructor");}public Object newInstance(final int n, final Object[] array) throws InvocationTargetException {try {switch (n) {case 0: {return new JDKFTPService$$EnhancerByCGLIB$$5a7831ef();}}}catch (Throwable t) {throw new InvocationTargetException(t);}throw new IllegalArgumentException("Cannot find matching method/constructor");}public int getMaxIndex() {return 20;} }// 里面使用 extends FastClass // 子類重寫父類的方法 // 父類方法不能是final復制代碼CGLib 和 JDK 動態代理對比
靜態代理和動態的本質區別
-
代理模式能將代理對象與真實被調用的目標對象分離。
-
一定程度上降低了系統的耦合度,擴展性好。
-
可以起到保護目標對象的作用。
-
可以對目標對象的功能增強。
當然,代理模式也是有缺點的:
執行速度
ASM > javassist > 手寫的(java -> class -> 加載)
轉載于:https://juejin.im/post/5ce20b9ae51d4510843bb48e
總結
以上是生活随笔為你收集整理的RE|GoF23种设计模式-动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何成为一名大数据工程师?
- 下一篇: 新手入门 如何快速找到Python进阶路