• jdk动态代理底层实现


    jdk动态代理示例:

    package dao;

    import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;

    public class Test {
    static interface Subject1{
    void subject11();
    void subject12();
    }
    static interface Subject2{
    void subject21();
    void subject22();
    }

    static class SubjectImpl implements Subject1,Subject2{

    @Override
    public void subject11() {
    System.out.println("subject11");
    }

    @Override
    public void subject12() {
    System.out.println("subject12");
    }
    @Override
    public void subject21() {
    System.out.println("subject21");
    }
    @Override
    public void subject22() {
    System.out.println("subject22");
    }
    }

    static class ProxyInvocationHandler implements InvocationHandler {
    private Subject2 target;
    public ProxyInvocationHandler(Subject2 target) {
    this.target=target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.print("invoke 增强");
    return method.invoke(target, args);
    }

    }

    public static void main(String[] args) {
    // 保存生成的代理类的字节码文件
    System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
    Subject2 subject=new SubjectImpl();
    Subject2 subjectProxy=(Subject2) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new ProxyInvocationHandler(subject));
    subjectProxy.subject21();
    subjectProxy.subject22();




    }
    }

    输出结果:

    invoke 增强subject21
    invoke 增强subject22

    并在工程中生成$Proxy0.class

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //

    package dao;

    import dao.Test.Subject1;
    import dao.Test.Subject2;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;

    //单一继承,所以jdk动态代理不能通过继承实现而是通过接口实现
    //所有接口的方法都重写了
    //通过构造函数传入的InvocationHandler的invoke(代理类,method,参数列表)方法来执行增强方法
    final class $Proxy0 extends Proxy implements Subject1, Subject2 {
    private static Method m1;
    private static Method m4;
    private static Method m2;
    private static Method m6;
    private static Method m3;
    private static Method m5;
    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 void subject12() throws {
    try {
    super.h.invoke(this, m4, (Object[])null);
    } catch (RuntimeException | Error var2) {
    throw var2;
    } catch (Throwable var3) {
    throw new UndeclaredThrowableException(var3);
    }
    }

    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 subject22() throws {
    try {
    super.h.invoke(this, m6, (Object[])null);
    } catch (RuntimeException | Error var2) {
    throw var2;
    } catch (Throwable var3) {
    throw new UndeclaredThrowableException(var3);
    }
    }

    public final void subject11() throws {
    try {
    super.h.invoke(this, m3, (Object[])null);
    } catch (RuntimeException | Error var2) {
    throw var2;
    } catch (Throwable var3) {
    throw new UndeclaredThrowableException(var3);
    }
    }

    public final void subject21() throws {
    try {
    super.h.invoke(this, m5, (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"));
    m4 = Class.forName("dao.Test$Subject1").getMethod("subject12");
    m2 = Class.forName("java.lang.Object").getMethod("toString");
    m6 = Class.forName("dao.Test$Subject2").getMethod("subject22");
    m3 = Class.forName("dao.Test$Subject1").getMethod("subject11");
    m5 = Class.forName("dao.Test$Subject2").getMethod("subject21");
    m0 = Class.forName("java.lang.Object").getMethod("hashCode");
    } catch (NoSuchMethodException var2) {
    throw new NoSuchMethodError(var2.getMessage());
    } catch (ClassNotFoundException var3) {
    throw new NoClassDefFoundError(var3.getMessage());
    }
    }
    }

    Proxy.newProxyInstance:

    1. 生成代理类$Proxy的class文件

    2. 根据InvocationHandler参数类型得到$Proxy对应的Constructor

    3. 根据constructor生成$proxy实例

    public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
            throws IllegalArgumentException
        {
            Objects.requireNonNull(h);
    
            final Class<?>[] intfs = interfaces.clone();
            final SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
            }
    
            /*
             * Look up or generate the designated proxy class.
             */
            Class<?> cl = getProxyClass0(loader, intfs);
    
            /*
             * Invoke its constructor with the designated invocation handler.
             */
            try {
                if (sm != null) {
                    checkNewProxyPermission(Reflection.getCallerClass(), cl);
                }
            //private static final Class<?>[] constructorParams = { InvocationHandler.class };
          final Constructor<?> cons = cl.getConstructor(constructorParams); 

        final InvocationHandler ih = h;
      
    if (!Modifier.isPublic(cl.getModifiers())) {
    AccessController.doPrivileged(
    new PrivilegedAction<Void>()
    {
    public Void run() { cons.setAccessible(true); return null; } }); }

    return cons.newInstance(new Object[]{h}); }

    catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } }

    1. 生成代理类$Proxy的class文件

      如果代理类缓存中有相应classloader和interfaces生成的代理类,则直接返回

      否则,通过ProxyClassFactory生成proxy class

         **遍历接口:

         非public的接口将proxy生成在相同的包下(byte[])

         public的接口将proxy生成在com.sun.proxy包下(byte[])

        **使用类加载器将代理类的字节码文件加载到JVM中(class)

     /**
         * Generate a proxy class.  Must call the checkProxyAccess method
         * to perform permission checks before calling this.
         */
        private static Class<?> getProxyClass0(ClassLoader loader,
                                               Class<?>... interfaces) {
            if (interfaces.length > 65535) {
                throw new IllegalArgumentException("interface limit exceeded");
            }
    
            // If the proxy class defined by the given loader implementing
            // the given interfaces exists, this will simply return the cached copy;
            // otherwise, it will create the proxy class via the ProxyClassFactory
            return proxyClassCache.get(loader, interfaces);  
        }

    ProxyClassFactory是Proxy的一个内部类

    /**
    * A factory function that generates, defines and returns the proxy class given
    * the ClassLoader and array of interfaces.
    */
    private static final class ProxyClassFactory
    implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
    // prefix for all proxy class names
    private static final String proxyClassNamePrefix = "$Proxy";

    // next number to use for generation of unique proxy class names
    private static final AtomicLong nextUniqueNumber = new AtomicLong();

    @Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

    Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
    for (Class<?> intf : interfaces) {
    /*
    * Verify that the class loader resolves the name of this
    * interface to the same Class object.
    */
    Class<?> interfaceClass = null;
    try {
    interfaceClass = Class.forName(intf.getName(), false, loader);
    } catch (ClassNotFoundException e) {
    }
    if (interfaceClass != intf) {
    throw new IllegalArgumentException(
    intf + " is not visible from class loader");
    }
    /*
    * Verify that the Class object actually represents an
    * interface.
    */
    if (!interfaceClass.isInterface()) {
    throw new IllegalArgumentException(
    interfaceClass.getName() + " is not an interface");
    }
    /*
    * Verify that this interface is not a duplicate.
    */
    if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
    throw new IllegalArgumentException(
    "repeated interface: " + interfaceClass.getName());
    }
    }

    String proxyPkg = null; // package to define proxy class in
    int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

    /*
    * Record the package of a non-public proxy interface so that the
    * proxy class will be defined in the same package. Verify that
    * all non-public proxy interfaces are in the same package.
    */
    for (Class<?> intf : interfaces) {
    int flags = intf.getModifiers();
    if (!Modifier.isPublic(flags)) {
    accessFlags = Modifier.FINAL;
    String name = intf.getName();
    int n = name.lastIndexOf('.');
    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
    if (proxyPkg == null) {
    proxyPkg = pkg;
    } else if (!pkg.equals(proxyPkg)) {
    throw new IllegalArgumentException(
    "non-public interfaces from different packages");
    }
    }
    }

    if (proxyPkg == null) {
    // if no non-public proxy interfaces, use com.sun.proxy package
    proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
    }

    /*
    * Choose a name for the proxy class to generate.
    */
    long num = nextUniqueNumber.getAndIncrement();
    String proxyName = proxyPkg + proxyClassNamePrefix + num;

    /*
    * Generate the specified proxy class.
    */
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
    proxyName, interfaces, accessFlags);
    try {
            //是一个native方法,使用类加载器将代理类的字节码文件加载到JVM中
    
    

    return defineClass0(loader, proxyName,
    proxyClassFile, 0, proxyClassFile.length);
    } catch (ClassFormatError e) {
    /*
    * A ClassFormatError here means that (barring bugs in the
    * proxy class generation code) there was some other
    * invalid aspect of the arguments supplied to the proxy
    * class creation (such as virtual machine limitations
    * exceeded).
    */
    throw new IllegalArgumentException(e.toString());
    }
    }
    }
     private static native Class<?> defineClass0(ClassLoader loader, String name,
                                                    byte[] b, int off, int len);
    public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
            ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
            final byte[] var4 = var3.generateClassFile();
            if (saveGeneratedFiles) //是否要将生成的$Proxy<NUM>.class保存到工程中
    { AccessController.doPrivileged(
    new PrivilegedAction<Void>() { public Void run() { try { int var1 = var0.lastIndexOf(46); //46代表. Path var2; if (var1 > 0) { Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar)); Files.createDirectories(var3); var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class"); } else { var2 = Paths.get(var0 + ".class"); } Files.write(var2, var4, new OpenOption[0]); return null; } catch (IOException var4x) { throw new InternalError("I/O exception saving generated file: " + var4x); } } }); } return var4; }
     private byte[] generateClassFile() {
         //为代理类生成hashCodeequals oString 方法
    this.addProxyMethod(hashCodeMethod, Object.class); this.addProxyMethod(equalsMethod, Object.class); this.addProxyMethod(toStringMethod, Object.class); Class[] var1 = this.interfaces; int var2 = var1.length; int var3; Class var4; for(var3 = 0; var3 < var2; ++var3) { var4 = var1[var3]; Method[] var5 = var4.getMethods(); int var6 = var5.length; for(int var7 = 0; var7 < var6; ++var7) { Method var8 = var5[var7]; this.addProxyMethod(var8, var4); } } Iterator var11 = this.proxyMethods.values().iterator(); List var12; while(var11.hasNext()) { var12 = (List)var11.next(); checkReturnTypes(var12); } Iterator var15; try { this.methods.add(this.generateConstructor()); var11 = this.proxyMethods.values().iterator(); while(var11.hasNext()) { var12 = (List)var11.next(); var15 = var12.iterator(); while(var15.hasNext()) { ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next(); this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10)); this.methods.add(var16.generateMethod()); } } this.methods.add(this.generateStaticInitializer()); } catch (IOException var10) { throw new InternalError("unexpected I/O Exception", var10); } if (this.methods.size() > 65535) { throw new IllegalArgumentException("method limit exceeded"); } else if (this.fields.size() > 65535) { throw new IllegalArgumentException("field limit exceeded"); } else { this.cp.getClass(dotToSlash(this.className)); this.cp.getClass("java/lang/reflect/Proxy"); var1 = this.interfaces; var2 = var1.length; for(var3 = 0; var3 < var2; ++var3) { var4 = var1[var3]; this.cp.getClass(dotToSlash(var4.getName())); } this.cp.setReadOnly(); ByteArrayOutputStream var13 = new ByteArrayOutputStream(); DataOutputStream var14 = new DataOutputStream(var13); try { var14.writeInt(-889275714); var14.writeShort(0); var14.writeShort(49); this.cp.write(var14); var14.writeShort(this.accessFlags); var14.writeShort(this.cp.getClass(dotToSlash(this.className))); var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy")); var14.writeShort(this.interfaces.length); Class[] var17 = this.interfaces; int var18 = var17.length; for(int var19 = 0; var19 < var18; ++var19) { Class var22 = var17[var19]; var14.writeShort(this.cp.getClass(dotToSlash(var22.getName()))); } var14.writeShort(this.fields.size()); var15 = this.fields.iterator(); while(var15.hasNext()) { ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next(); var20.write(var14); } var14.writeShort(this.methods.size()); var15 = this.methods.iterator(); while(var15.hasNext()) { ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next(); var21.write(var14); } var14.writeShort(0); return var13.toByteArray(); } catch (IOException var9) { throw new InternalError("unexpected I/O Exception", var9); } } }
  • 相关阅读:
    django 中 slice 和 truncatewords 不同用法???
    js如何获取到select的option值???
    MySQL的btree索引和hash索引的区别
    Python3之Django Web框架中间件???
    2019.07.25考试报告
    2019.07.19考试报告
    2019.07.18考试报告
    2019.07.16考试报告
    2019.07.12考试报告
    ELK+Kafka
  • 原文地址:https://www.cnblogs.com/yintingting/p/6186218.html
Copyright © 2020-2023  润新知