Java动态代理深入解析(6)

} finally {
            /*
            * We must clean up the "pending generation" state of the proxy
            * class cache entry somehow.  If a proxy class was successfully
            * generated, store it in the cache (with a weak reference);
            * otherwise, remove the reserved entry.  In all cases, notify
            * all waiters on reserved entries in this cache.
            */
       //创建成功,则将cache中该key的pendingGenerationMarker替换为实际的代理类的弱引用,否则也要清除pendingGenerationMarker标记;不管是否成功,都要执行cache.notifyAll(),让其它要创建相同代理类并且执行了cache.wait()的线程恢复执行。
            synchronized (cache) {
                if (proxyClass != null) {
                    cache.put(key, new WeakReference<Class<?>>(proxyClass));
                } else {
                    cache.remove(key);
                }
                cache.notifyAll();
            }
        }
        return proxyClass; //最后返回代理类Class
    }

到这里,我们已经把动态代理的java源代码都解析完了,现在思路就很清晰了:

Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法简单来说执行了以下操作:

1.生成一个实现了参数interfaces里所有接口且继承了Proxy的代理类的字节码,然后用参数里的classLoader加载这个代理类。

2.使用代理类父类的构造函数 Proxy(InvocationHandler h)来创造一个代理类的实例,将我们自定义的InvocationHandler的子类传入。

3.返回这个代理类实例,因为我们构造的代理类实现了interfaces(也就是我们程序中传入的subject.getClass().getInterfaces())里的所有接口,因此返回的代理类可以强转成Subject类型来调用接口中定义的方法。

现在我们知道了用Proxy.newProxyInstance()返回的subjectProxy可以成功强转成Subject类型来调用接口中定义的方法了,那么在调用方法后,代理类实例怎么进行处理的呢,这就需要看一下代理类的源码了。但是代理类是程序动态生成字节码加载的,怎么看源码呢?没关系,可以在main方法中加入System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"),这样就会把生成的代理类Class文件保存在本地磁盘上,然后再反编译可以得到代理类的源码:

package common;

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 Test.Subject
{
  private static Method m4;
  private static Method m1;
  private static Method m3;
  private static Method m0;
  private static Method m2;
 
  static
  {
      try {
          m4 = Class.forName("Test$Subject").getMethod("sayHello", new Class[0]);
          m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
          m3 = Class.forName("Test$Subject").getMethod("sayHi", new Class[0]);
          m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
          m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
  }

public $Proxy0(InvocationHandler paramInvocationHandler)
  {
    super(paramInvocationHandler);
  }

public final void sayHello()
  {
    try
    {
      this.h.invoke(this, m4, null);
      return;
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
        throw new UndeclaredThrowableException(localThrowable);
    }
  }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/0dab0fb138c3829c8bf6ef3b552a8a73.html