java动态代理中的invoke方法是如何被自动调用的(二)

2014-11-23 23:56:39 · 作者: · 浏览: 1
stract void ***.Subject.request()
  • From real subject.
  • after calling public abstract void ***.Subject.request()

    PS:这个结果的信息非常重要,至少对我来说。因为我在动态代理犯晕的根源就在于将上面的subject.request()理解错了,至少是被表面所迷惑,没有发现这个subject和Proxy之间的联系,一度纠结于最后调用的这个request()是怎么和invoke()联系上的,而invoke又是怎么知道request存在的。其实上面的true和class $Proxy0就能解决很多的疑问,再加上下面将要说的$Proxy0的源码,完全可以解决动态代理的疑惑了。

    从以上代码和结果可以看出,我们并没有显示的调用invoke()方法,但是这个方法确实执行了。下面就整个的过程进行分析一下:

    从Client中的代码看,可以从newProxyInstance这个方法作为突破口,我们先来看一下Proxy类中newProxyInstance方法的源代码:
    Java代码 收藏代码
    1. public static Object newProxyInstance(ClassLoader loader,
    2. Class [] interfaces,
    3. InvocationHandler h)
    4. throws IllegalArgumentException
    5. {
    6. if (h == null) {
    7. throw new NullPointerException();
    8. }
    9. /*
    10. * Look up or generate the designated proxy class.
    11. */
    12. Class cl = getProxyClass(loader, interfaces);
    13. /*
    14. * Invoke its constructor with the designated invocation handler.
    15. */
    16. try {
    17. /*
    18. * Proxy源码开始有这样的定义:
    19. * private final static Class[] constructorParams = { InvocationHandler.class };
    20. * cons即是形参为InvocationHandler类型的构造方法
    21. */
    22. Constructor cons = cl.getConstructor(constructorParams);
    23. return (Object) cons.newInstance(new Object[] { h });
    24. } catch (NoSuchMethodException e) {
    25. throw new InternalError(e.toString());
    26. } catch (IllegalAccessException e) {
    27. throw new InternalError(e.toString());
    28. } catch (InstantiationException e) {
    29. throw new InternalError(e.toString());
    30. } catch (InvocationTargetException e) {
    31. throw new InternalError(e.toString());
    32. }
    33. }

      Proxy.newProxyInstance(ClassLoader loader, Class [] interfaces, InvocationHandler h)做了以下几件事.
      (1)根据参数loader和interfaces调用方法 getProxyClass(loader, interfaces)创建代理类$Proxy0.$Proxy0类 实现了interfaces的接口,并继承了Proxy类.
      (2)实例化$Proxy0并在构造方法中把DynamicSubject传过去,接着$Proxy0调用父类Proxy的构造器,为h赋值,如下:
      Java代码 收藏代码
      1. class Proxy{
      2. InvocationHandler h=null;
      3. protected Proxy(InvocationHandler h) {
      4. this.h = h;
      5. }
      6. ...
      7. }

        来看一下这个继承了Proxy的$Proxy0的源代码:
        Java代码 收藏代码
        1. public final class $Proxy0 extends Proxy implements Subject {
        2. private static Method m1;
        3. private static Method m0;
        4. private static Method m3;
        5. private static Method m2;
        6. static {
        7. try {
        8. m1 = Class.forName("java.lang.Object").getMethod("equals",
        9. new Class[] { Class.forName("java.lang.Object") });
        10. m0 = Class.forName("java.lang.Object").getMethod("hashCode",
        11. new Class[0]);
        12. m3 = Class.forName("***.RealSubject").getMethod("request",
        13. new Class[0]);
        14. m2 = Class.forName("java.lang.Object").getMethod("toString",
        15. new Class[0]);
        16. } catch (NoSuchMethodException nosuchmethodexception) {
        17. throw new NoSuchMethodError(nosuchmethodexception.getMessage());
        18. } catch (ClassNotFoundException classnotfoundexception) {
        19. throw new NoClassDefFoundError(classnotfoundexception.getMessage());
        20. }
        21. } //static
        22. public $Proxy0(InvocationHandler invocationhandler) {
        23. super(invocationhandler);
        24. }
        25. @Override
        26. public final boolean equals(Object obj) {
        27. try {
        28. return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();
        29. } catch (Throwable throwable) {
        30. throw new UndeclaredThrowableException(throwable);
        31. }
        32. }
        33. @Override
        34. public final int hashCode() {
        35. try {
        36. return ((Integer) super.h.invoke(this, m0, null)).intValue();
        37. } catch (Throwable throwable) {
        38. throw new UndeclaredThrowableException(throwable);
        39. }
        40. }
        41. public final void request() {
        42. try {
        43. super.h.invoke(this, m3, null);
        44. return;
        45. }