内容简介:代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。符合开闭原则。代理模式属于结构型 模式,有静态代理和动态代理。需求:现在我们需要根据类型来分别把数据上传到不同Ftp服务。动态代理有以下特点:
代理(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 { @Override 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; } @Override 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的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
- 动态代理也叫做: JDK代理,接口代理
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 { @Override 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); } @Override 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"); else System.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 生成对象的步骤如下:
- 拿到被代理对象的引用,并且获取到它的所有的接口,反射获取。
- JDK Proxy 类重新生成一个新的类、同时新的类要实现被代理类所有实现的所有的接口。
- 动态生成 Java 代码,把新加的业务逻辑方法由一定的逻辑代码去调用(在代码中体现)。
- 编译新生成的 Java 代码.class。
- 再重新加载到 JVM 中运行。
public static void main(String[] args) throws IOException { //通过反编译 工具 可以查看源代码 byte [] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{IFTPService.class}); FileOutputStream os = new FileOutputStream("E://$Proxy0.class"); os.write(bytes); os.close(); } 复制代码
使用反编译工具,得到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."); } @Override 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.jar public 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 { @Override 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(); } @Override 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"); else System.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 动态代理对比
- JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。
- JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。
- JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法, CGLib 执行效率更高。
静态代理和动态的本质区别
- 静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步 新增,违背开闭原则。
- 动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开 闭原则。
- 若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成, 无需修改代理类的代码。 代理模式的优缺点 使用代理模式具有以下几个优点:
-
代理模式能将代理对象与真实被调用的目标对象分离。
-
一定程度上降低了系统的耦合度,扩展性好。
-
可以起到保护目标对象的作用。
-
可以对目标对象的功能增强。
当然,代理模式也是有缺点的:
- 代理模式会造成系统设计中类的数量增加。
- 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
- 增加了系统的复杂度。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 设计模式——订阅模式(观察者模式)
- 设计模式-简单工厂、工厂方法模式、抽象工厂模式
- java23种设计模式-门面模式(外观模式)
- 设计模式-享元设计模式
- Java 设计模式之工厂方法模式与抽象工厂模式
- JAVA设计模式之模板方法模式和建造者模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。