内容简介:缺点:JDKcblib
public interface Person { String searchHouse(); } 复制代码
public class MasterProxy implements Person { private Person person; public MasterProxy(Person person) { this.person = person; } @Override public String searchHouse() { System.out.println("我是链家,我帮别人找房子.."); //第一个参数是target,也就是被代理类的对象;第二个参数是方法中的参数 String msg = person.searchHouse(); System.out.println("------------------------"); System.out.println("| | |"); System.out.println("| | |"); System.out.println("| | |"); System.out.println("|------- ------- -----"); System.out.println(" |"); System.out.println("|----------------------|"); System.out.println("我是链家,已经找到了.."); return msg; } } 复制代码
public class ProxyTest { @Test public void testJDKObject() { Person person = new Master(); MasterProxy masterProxy = new MasterProxy(person); String sb = masterProxy.searchHouse(); System.out.println(sb); } } 复制代码
缺点:
- 代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。
- 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护。增加了代码维护的复杂度。
- 静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类
动态代理的两种方式
代理对象
public class Master implements Person{ @Override public String searchHouse() { System.out.println("我需要找一个整租两室一厅的房子"); return "done"; } public static String pay() { System.out.println("我支付了"); return "我支付了"; } public final String sign() { System.out.println("我签约了"); return "我签约了"; } } 复制代码
JDK
/** * 代理对象,不需要实现接口 * * 代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理 * @param <T> */ public class HomeLineJDK<T> implements InvocationHandler { private Person target; public T createProxyInstance(Person target){ this.target = target; Class clazz = target.getClass(); //指定当前目标对象使用类加载器,获取加载器的方法是固定的 //目标对象实现的接口的类型,使用泛型方式确认类型 //事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入 T obj = (T)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); // new ProxyClass().getClazz("jdkObject"); return obj; } public T createProxyInstance(Class clazz){ T obj = (T)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); new ProxyClass().getClazz("jdkClass"); return obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //System.out.println("我是链家,我帮别人找房子.."); //第一个参数是target,也就是被代理类的对象;第二个参数是方法中的参数 Object msg = method.invoke(target, args); System.out.println("我是链家,已经找到了.."); return msg; } } 复制代码
- 代理对象,不需要实现接口
- 代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
cblib
/** * Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展. */ public class HomeLineCglib implements MethodInterceptor { private Object target; public <T> T createProxyInstance(T targetObject){ this.target = targetObject; //给业务对象赋值 Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类 也就是cglib中的一个class generator enhancer.setSuperclass(this.target.getClass()); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类) //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦 enhancer.setCallback(this); // 创建动态代理类对象并返回 T o = (T)enhancer.create(); // new ProxyClass().getCglibClazz(enhancer); return o; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("我是链家,我帮别人找房子.."); //第一个参数是target,也就是被代理类的对象;第二个参数是方法中的参数 Object msg = methodProxy.invoke(this.target, objects); System.out.println("我是链家,已经找完了.."); return msg; } } 复制代码
测试:
public class InvacationTest { @Test public void testJDKObject() { Person person = new HomeLineJDK<Person>().createProxyInstance(new Master()); String sb = person.searchHouse(); // System.out.println(sb); } @Test public void testJDKCLass() { Person person1 = new HomeLineJDK<Person>().createProxyInstance(Master.class); String sb1 = person1.searchHouse(); System.out.println(sb1); } @Test public void testCglib() { Master master = new Master(); master = new HomeLineCglib().createProxyInstance(master); master.searchHouse(); } @Test public void testStaticCglib() { Master master = new Master(); master = new HomeLineCglib().createProxyInstance(master); master.pay(); } @Test public void testFinalCglib() { Master master = new Master(); master = new HomeLineCglib().createProxyInstance(master); master.sign(); } } 复制代码
获取代理对象
public class ProxyClass { public void getClazz(String fileName){ String path = "D://"+fileName+".class"; byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0",Master.class.getInterfaces()); FileOutputStream out = null; try { out = new FileOutputStream(path); out.write(classFile); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } public void getCglibClazz(Enhancer enhancer){ String path = "D://cglib.class"; byte[] classFile = new byte[0]; try { classFile = enhancer.getStrategy().generate(enhancer); } catch (Exception e) { e.printStackTrace(); } FileOutputStream out = null; try { out = new FileOutputStream(path); out.write(classFile); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } 复制代码
代理对象源码解析:
- jdk对应的字节码对象
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; import services.proxy.Person; public final class $Proxy0 extends Proxy implements Person { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final String searchHouse() throws { try { return (String)super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("services.proxy.Person").getMethod("searchHouse"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } } 复制代码
- cglib对应的字节码对象
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; import services.proxy.Person; public final class $Proxy0 extends Proxy implements Person { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final String searchHouse() throws { try { return (String)super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("services.proxy.Person").getMethod("searchHouse"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } } 复制代码
两种代理模式性能比较:
package services.proxy; import org.junit.Test; public class ProxyPerofrmanceTest { @Test public void testTime(){ testCglibCreateTime(10000); testJdkCreateTime(10000); System.out.println("-------------------"); testCglibExecuteTime(10); testCglibExecuteTime(100); testCglibExecuteTime(1000); testCglibExecuteTime(10000); testCglibExecuteTime(100000); testCglibExecuteTime(1000000); testCglibExecuteTime(10000000); System.out.println("-------------------"); System.out.println("-------------------"); testJdkExecuteTime(10); testJdkExecuteTime(100); testJdkExecuteTime(1000); testJdkExecuteTime(10000); testJdkExecuteTime(100000); testJdkExecuteTime(1000000); testJdkExecuteTime(10000000); } public void testJdkExecuteTime(int times){ Person person = new HomeLineJDK<Person>().createProxyInstance(new Master()); long jdks = System.currentTimeMillis(); for (int i = 0;i<times;i++){ person.searchHouse(); } long jdke = System.currentTimeMillis(); System.out.println("jdk"+times+"次执行方法处处理时间:"+(jdke-jdks)); } public void testJdkCreateTime(int times){ long jdks = System.currentTimeMillis(); for (int i = 0;i<times;i++){ Person person = new HomeLineJDK<Person>().createProxyInstance(new Master()); } long jdke = System.currentTimeMillis(); System.out.println("jkd创建代理对象"+times+"次处理时间:"+(jdke-jdks)); } } 复制代码
jdk和cglib第一次创建对象会将对象缓存,所以我们先创建一次去掉创建对象时间
jdk | cglib |
---|---|
2 ms | 228 ms |
接下来我们看执行对应方法的耗时
次数 | jdk | cglib |
---|---|---|
10 | 0 | 17 |
100 | 1 | 0 |
1000 | 0 | 1 |
10000 | 2 | 4 |
100000 | 5 | 4 |
1000000 | 13 | 9 |
10000000 | 94 | 44 |
可以看到在创建对象并缓存到内存中的时候,cglib耗时比较jdk严重。但是在正直的执行过程中我们可以看到开始的时候jdk的性能优于cglib当达到一定调用量的时候cglib的性能较jdk要好。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Nacos 0.3.0 发布,迄今为止看着最舒服的版本
- 【Vue.js 实例】vue.js看着官方文档的从0开始瞎摸学习
- 当当图书大促仅剩最后3小时!Flink新书在当当、京东全部卖脱销!买不买你自己看着办咯~
- 设计模式——订阅模式(观察者模式)
- 设计模式-简单工厂、工厂方法模式、抽象工厂模式
- java23种设计模式-门面模式(外观模式)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。