美文网首页
java动态代理

java动态代理

作者: KubiL | 来源:发表于2017-04-17 23:44 被阅读0次

    目录:

    • 简介
    • jdk动态代理
    • cglib动态代理
    • jdk动态代理与cglib的区别
    • 应用spring的aop

    简介

    动态代理是在不修改原有代码的基础上动态增强类的职责,两种实现方式,一种是jdk自带或cglib中实现的,主要应用有spring aop、记录日志、事物管理等。

    jdk动态代理

    jdk动态代理是基于java的反射机制动态生成代理类从而实现代理。
    要求:被代理类实现接口

    例子:

    Paste_Image.png
    
    public interface Subject {
        public void helloWorld();
    }
    
    
    
    public class RealSubject implements Subject{
    
        @Override
        public void helloWorld() {
            System.out.println("say hello to the world");
        }
    }
    
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    
    public class MyHandler implements InvocationHandler{
        private Object target;
        public MyHandler(Object obj){
            this.target = obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println("do something before");
            method.invoke(target, args);
            System.out.println("do something after");
            return null;
        }
    
    }
    
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    public class Client {
        public static void main(String[] args) {
            RealSubject realsub = new RealSubject();
            InvocationHandler handler = new MyHandler(realsub);
            Subject sub = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), 
                    RealSubject.class.getInterfaces(), handler);
            sub.helloWorld();
        }
    }
    
    

    网上找到反编译后的$Proxy0

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    public final class $Proxy0 extends Proxy implements Subject{
    
    private static Method m1;
    private static Method m0;
    private static Method m3;
    private static Method m2;
    
    static {
       try {
        m1 = Class.forName("java.lang.Object").getMethod("equals",
          new Class[] { Class.forName("java.lang.Object") });
        m0 = Class.forName("java.lang.Object").getMethod("hashCode",
          new Class[0]);
        m3 = Class.forName("Subject").getMethod("helloWorld",
          new Class[0]);
        m2 = Class.forName("java.lang.Object").getMethod("toString",
          new Class[0]);
       } catch (NoSuchMethodException nosuchmethodexception) {
        throw new NoSuchMethodError(nosuchmethodexception.getMessage());
       } catch (ClassNotFoundException classnotfoundexception) {
        throw new NoClassDefFoundError(classnotfoundexception.getMessage());
       }
    }
    
    public $Proxy0(InvocationHandler invocationhandler) {
       super(invocationhandler);
    }
    
    @Override
    public final boolean equals(Object obj) {
       try {
        return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
          .booleanValue();
       } catch (Throwable throwable) {
        throw new UndeclaredThrowableException(throwable);
       }
    }
    
    @Override
    public final int hashCode() {
       try {
        return ((Integer) super.h.invoke(this, m0, null)).intValue();
       } catch (Throwable throwable) {
        throw new UndeclaredThrowableException(throwable);
       }
    }
    
    public final void helloWorld() {
       try {
        super.h.invoke(this, m3, null);
        return;
       } catch (Error e) {
       } catch (Throwable throwable) {
        throw new UndeclaredThrowableException(throwable);
       }
    }
    
    @Override
    public final String toString() {
       try {
        return (String) super.h.invoke(this, m2, null);
       } catch (Throwable throwable) {
        throw new UndeclaredThrowableException(throwable);
       }
    }
    }
    

    cglib动态代理

    使用cglib[Code Generation Library]实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码。
    核心:通过继承实现代理
    例子:

    public class RealSubject {
        public void helloWorld() {
            System.out.println("say hello to the world");
        }
    }
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class CglibProxy implements MethodInterceptor{
        public  Object createProxy(Class clazz){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(this);
            return enhancer.create();
        }
        @Override
        public Object intercept(Object obj, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            System.out.println("do before ");
            Object result = methodProxy.invokeSuper(obj, args);
            System.out.println("do after ");
            return result;
        }
        
    }
    
    import net.sf.cglib.core.DebuggingClassWriter;
    
    public class Client {
        public static void main(String[] args) {
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "G:\\code");
            CglibProxy  proxy = new CglibProxy();
            RealSubject proxySubject = (RealSubject) proxy.createProxy(RealSubject.class);
            proxySubject.helloWorld();
        }
    }
    

    RealSubject$$EnhancerByCGLIB$$8f2454c.class

    import java.lang.reflect.Method;
    import net.sf.cglib.core.ReflectUtils;
    import net.sf.cglib.core.Signature;
    import net.sf.cglib.proxy.Callback;
    import net.sf.cglib.proxy.Factory;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class RealSubject$$EnhancerByCGLIB$$8f2454c extends RealSubject
      implements Factory
    {
      private boolean CGLIB$BOUND;
      private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
      private static final Callback[] CGLIB$STATIC_CALLBACKS;
      private MethodInterceptor CGLIB$CALLBACK_0;
      private static final Method CGLIB$helloWorld$0$Method;
      private static final MethodProxy CGLIB$helloWorld$0$Proxy;
      private static final Object[] CGLIB$emptyArgs;
      private static final Method CGLIB$finalize$1$Method;
      private static final MethodProxy CGLIB$finalize$1$Proxy;
      private static final Method CGLIB$equals$2$Method;
      private static final MethodProxy CGLIB$equals$2$Proxy;
      private static final Method CGLIB$toString$3$Method;
      private static final MethodProxy CGLIB$toString$3$Proxy;
      private static final Method CGLIB$hashCode$4$Method;
      private static final MethodProxy CGLIB$hashCode$4$Proxy;
      private static final Method CGLIB$clone$5$Method;
      private static final MethodProxy CGLIB$clone$5$Proxy;
    
      static void CGLIB$STATICHOOK1()
      {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class localClass1 = Class.forName("cglib.RealSubject$$EnhancerByCGLIB$$8f2454c");
        Class localClass2;
        Method[] tmp50_47 = ReflectUtils.findMethods(new String[] { "helloWorld", "()V" }, (localClass2 = Class.forName("cglib.RealSubject")).getDeclaredMethods());
        CGLIB$helloWorld$0$Method = tmp50_47[0];
        CGLIB$helloWorld$0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "helloWorld", "CGLIB$helloWorld$0");
        tmp50_47;
        Method[] tmp143_140 = ReflectUtils.findMethods(new String[] { "finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (localClass2 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$finalize$1$Method = tmp143_140[0];
        CGLIB$finalize$1$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "finalize", "CGLIB$finalize$1");
        Method[] tmp163_143 = tmp143_140;
        CGLIB$equals$2$Method = tmp163_143[1];
        CGLIB$equals$2$Proxy = MethodProxy.create(localClass2, localClass1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        Method[] tmp183_163 = tmp163_143;
        CGLIB$toString$3$Method = tmp183_163[2];
        CGLIB$toString$3$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        Method[] tmp203_183 = tmp183_163;
        CGLIB$hashCode$4$Method = tmp203_183[3];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(localClass2, localClass1, "()I", "hashCode", "CGLIB$hashCode$4");
        Method[] tmp223_203 = tmp203_183;
        CGLIB$clone$5$Method = tmp223_203[4];
        CGLIB$clone$5$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
        tmp223_203;
        return;
      }
    
      final void CGLIB$helloWorld$0()
      {
        super.helloWorld();
      }
    
      public final void helloWorld()
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        if (this.CGLIB$CALLBACK_0 != null)
          return;
        super.helloWorld();
      }
    
      final void CGLIB$finalize$1()
        throws Throwable
      {
        super.finalize();
      }
    
      protected final void finalize()
        throws Throwable
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        if (this.CGLIB$CALLBACK_0 != null)
          return;
        super.finalize();
      }
    
      final boolean CGLIB$equals$2(Object paramObject)
      {
        return super.equals(paramObject);
      }
    
      public final boolean equals(Object paramObject)
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null)
        {
          Object tmp41_36 = tmp17_14.intercept(this, CGLIB$equals$2$Method, new Object[] { paramObject }, CGLIB$equals$2$Proxy);
          tmp41_36;
          return tmp41_36 == null ? false : ((Boolean)tmp41_36).booleanValue();
        }
        return super.equals(paramObject);
      }
    
      final String CGLIB$toString$3()
      {
        return super.toString();
      }
    
      public final String toString()
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null)
          return (String)tmp17_14.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy);
        return super.toString();
      }
    
      final int CGLIB$hashCode$4()
      {
        return super.hashCode();
      }
    
      public final int hashCode()
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null)
        {
          Object tmp36_31 = tmp17_14.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
          tmp36_31;
          return tmp36_31 == null ? 0 : ((Number)tmp36_31).intValue();
        }
        return super.hashCode();
      }
    
      final Object CGLIB$clone$5()
        throws CloneNotSupportedException
      {
        return super.clone();
      }
    
      protected final Object clone()
        throws CloneNotSupportedException
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null)
          return tmp17_14.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy);
        return super.clone();
      }
    
      public static MethodProxy CGLIB$findMethodProxy(Signature paramSignature)
      {
        String tmp4_1 = paramSignature.toString();
        switch (tmp4_1.hashCode())
        {
        case -1574182249:
          if (tmp4_1.equals("finalize()V"))
            return CGLIB$finalize$1$Proxy;
        case -508378822:
        case 494307733:
        case 1826985398:
        case 1913648695:
        case 1984935277:
        }
      }
    
      public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback)
      {
        CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
      }
    
      public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback)
      {
        CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
      }
    
      private static final void CGLIB$BIND_CALLBACKS(Object paramObject)
      {
        // Byte code:
        //   0: aload_0
        //   1: checkcast 2 cglib/RealSubject$$EnhancerByCGLIB$$8f2454c
        //   4: astore_1
        //   5: aload_1
        //   6: getfield 198    cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$BOUND Z
        //   9: ifne +43 -> 52
        //   12: aload_1
        //   13: iconst_1
        //   14: putfield 198   cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$BOUND Z
        //   17: getstatic 24   cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$THREAD_CALLBACKS  Ljava/lang/ThreadLocal;
        //   20: invokevirtual 201  java/lang/ThreadLocal:get   ()Ljava/lang/Object;
        //   23: dup
        //   24: ifnonnull +15 -> 39
        //   27: pop
        //   28: getstatic 196  cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$STATIC_CALLBACKS  [Lnet/sf/cglib/proxy/Callback;
        //   31: dup
        //   32: ifnonnull +7 -> 39
        //   35: pop
        //   36: goto +16 -> 52
        //   39: checkcast 202  [Lnet/sf/cglib/proxy/Callback;
        //   42: aload_1
        //   43: swap
        //   44: iconst_0
        //   45: aaload
        //   46: checkcast 48   net/sf/cglib/proxy/MethodInterceptor
        //   49: putfield 36    cglib/RealSubject$$EnhancerByCGLIB$$8f2454c:CGLIB$CALLBACK_0    Lnet/sf/cglib/proxy/MethodInterceptor;
        //   52: return
      }
    
      public Object newInstance(Callback[] paramArrayOfCallback)
      {
        CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
        CGLIB$SET_THREAD_CALLBACKS(null);
        return new 8f2454c();
      }
    
      public Object newInstance(Callback paramCallback)
      {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[] { paramCallback });
        CGLIB$SET_THREAD_CALLBACKS(null);
        return new 8f2454c();
      }
    
      public Object newInstance(Class[] paramArrayOfClass, Object[] paramArrayOfObject, Callback[] paramArrayOfCallback)
      {
        CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
        Class[] tmp9_8 = paramArrayOfClass;
        switch (tmp9_8.length)
        {
        case 0:
          tmp9_8;
          break;
        default:
          new 8f2454c();
          throw new IllegalArgumentException("Constructor not found");
        }
        CGLIB$SET_THREAD_CALLBACKS(null);
      }
    
      public Callback getCallback(int paramInt)
      {
        CGLIB$BIND_CALLBACKS(this);
        switch (paramInt)
        {
        case 0:
          break;
        }
        return null;
      }
    
      public void setCallback(int paramInt, Callback paramCallback)
      {
        switch (paramInt)
        {
        case 0:
          this.CGLIB$CALLBACK_0 = ((MethodInterceptor)paramCallback);
          break;
        }
      }
    
      public Callback[] getCallbacks()
      {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[] { this.CGLIB$CALLBACK_0 };
      }
    
      public void setCallbacks(Callback[] paramArrayOfCallback)
      {
        this.CGLIB$CALLBACK_0 = ((MethodInterceptor)paramArrayOfCallback[0]);
      }
    
      static
      {
        CGLIB$STATICHOOK1();
      }
    }
    

    jdk动态代理与cglib的区别

    JDK动态代理
    优点
    不依赖第三方jar包, 使用方便
    随着JDK的升级,JDK动态代理的性能在稳步提升

    缺点
    只能代理实现了接口的类
    执行速度较慢

    适用场景
    如果你的程序需要频繁、反复地创建代理对象,则JDK动态代理在性能上更占优。
    cglib
    优点
    由于是动态生成字节码实现代理,因此代理对象的执行速度较快, 约为JDK动态代理的1.5 ~ 2倍
    可以代理没有实现接口的对象

    缺点
    不能代理final

    动态生成字节码虽然执行较快,但是生成速度很慢,根据网上一些人的测试结果,cglib创建代理对象的速度要比JDK慢10 ~ 15倍。

    适用场景
    不需要频繁创建代理对象的应用,如spring中默认的单例bean,只需要在容器启动时生成一次代理对象。

    应用 spring aop

    被代理的类如果有实现的接口 优先使用jdk动态代理,否则用cglib动态代理。

    相关文章

      网友评论

          本文标题:java动态代理

          本文链接:https://www.haomeiwen.com/subject/sguzattx.html