随笔 - 11  文章 - 0  评论 - 0  0

JDK动态代理和CGLIB代理的区别:

  • JDK动态代理:其代理对象必须是某个接口的实现,他是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。
  • CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生产的代理对象是针对目标类扩展的子类,CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强

代码示例:

/**
 * jdk动态代理示例
 */
public class JdkProxy {
    //定义要被代理的接口
    static interface Subject {
        public void Sayhello();
    }

    //定义被代理的接口的实现类
    static class SubjectImp implements Subject {
        public void Sayhello() {
            System.out.print("hello");
        }
    }

    //定义被代理接口的处理器类
    static class ProxyHandle implements InvocationHandler {
        private Subject target;

        public ProxyHandle(Subject target) {
            this.target = target;
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object o = method.invoke(target, args);
            System.out.print(" mayu");
            return o;
        }
    }

    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        Subject subject = new SubjectImp();
        //生成代理对象
        Subject subjectProxy = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new ProxyHandle(subject));
        subjectProxy.Sayhello();
    }
}

运行结果:hello mayu

查看生成的代理类加上System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"),在项目的根路径上可以找到代理类,如下:

final class $Proxy0 extends Proxy implements Subject {
    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})).booleanValue();
        } 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 void Sayhello() throws  {
        try {
            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)).intValue();
        } 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("AOP.JdkProxy$Subject").getMethod("Sayhello");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

原理是通过JDK字节码生成技术将给定的目标方法和处理目标方法的处理器在运行期间进行方法提取和拼装生成新的代理类。

posted on 2019-08-04 09:46  LLCYZJ  阅读(...)  评论(... 编辑 收藏