動的エージェントProxy


 :
package com.atb.proxy.simple;

public interface ProxyInterface {
	public void methodPrint();
}


 :
package com.atb.proxy.simple;
public class ProxyImple implements ProxyInterface{
	private String aa="sss";
	public void methodPrint() {
		System.out.println("hi dubbo:"+aa);
	}
}

次はエージェントクラスとテストの具体的なコードです.
package com.atb.proxy.simple;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 *  
 * @author xieronghui
 */
public class DynamicProxy implements InvocationHandler {

	//  
    private Object proxyObject;
 
    /**
     *  , 
     */
    public Object bind(Object proxyObject) {
        this.proxyObject = proxyObject;
        /**
         *     loader  ;
         *                 interfaces  ( ProxyInterface)
         *                 h  InvocationHandler(DynamicProxy    InvocationHandler)
         * public static Object newProxyInstance(ClassLoader loader,
					  Class<?>[] interfaces,
					  InvocationHandler h)
         */
        return Proxy.newProxyInstance(proxyObject.getClass().getClassLoader(),
                proxyObject.getClass().getInterfaces(), this);
    }
    /**
     * $Proxy0  invoke  
     */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = method.invoke(proxyObject, args);
		return result;
	}
	
}

テスト対象
package com.atb.proxy.simple;

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

public class ProxyTest {
	public static void main(String[] args) throws SecurityException, NoSuchMethodException {
		DynamicProxy proxy=new DynamicProxy();
		ProxyInterface proxyInter=(ProxyInterface)proxy.bind(new ProxyImple());
		//proxyInter.methodPrint();
		   // proxyInter Proxy , proxyInter   
        System.out.println(proxyInter instanceof Proxy);  
          
        // proxyInter Class $Proxy0, $Proxy0 Proxy, proxyInter   
        System.out.println("ProxyInterface Class :"+proxyInter.getClass().toString());  
        System.out.print("ProxyInterface($Proxy0) :");  
        Field[] field=proxyInter.getClass().getDeclaredFields();  
        for(Field f:field){  
            System.out.print(f.getName()+", ");  
        }  
        System.out.print("
"+"ProxyInterface--->($Proxy0) :");           Method[] method=proxyInter.getClass().getDeclaredMethods();           for(Method m:method){               System.out.print(m.getName()+", ");           }           System.out.println("
"+"ProxyInterface ($Proxy0) :"+proxyInter.getClass().getSuperclass());           System.out.print("
"+"ProxyInterface ($Proxy0) :");                      Class<?>[] interfaces=proxyInter.getClass().getInterfaces();                      for(Class<?> i:interfaces){               System.out.print(i.getName()+", ");           }           System.out.println("
"+"# :");         proxyInter.methodPrint();    } }

結果を返します.
true
ProxyInterface Class :class $Proxy0
ProxyInterface($Proxy0) :m1, m3, m0, m2, 
ProxyInterface--->($Proxy0) :equals, toString, hashCode, methodPrint, 
ProxyInterface ($Proxy0) :class java.lang.reflect.Proxy
ProxyInterface ($Proxy0) :com.atb.proxy.simple.ProxyInterface, 
# :
hi dubbo:sss

ProxyInterfaceのClassクラスは:class$Proxy 0ここから見ることができます
     ProxyInterface proxyInter=(ProxyInterface)proxy.bind(new ProxyImple());
返されるClassは$Proxy 0であり、インタフェースがProxyImpleを実装するバイトコードではない.以前はProxyImpleのインスタンスがそのメソッドmethodPrint()を呼び出すことを理解していた.実際にはクラスローダによって$Proxy 0のオブジェクトが動的に構築されており、コンソール印刷で見ることができます.
ProxyInterface----($Proxy 0)では、equals,toString,hashCode,methodPrint、
ProxyInterface($Proxy 0)の親はclass java.lang.reflect.Proxy
$Proxy 0はいつ作られたのでしょうか
    public Object bind(Object proxyObject) {
        this.proxyObject = proxyObject;
       /**
*ここでは、loaderが動的にロードされたエージェントオブジェクトを表す方法を説明します.
*interfacesインタフェース(1つのクラスで複数のインタフェースを実現できますよねここではProxyInterfaceに相当します)
*h InvocationHandler(DynamicProxyオブジェクトがInvocationHandlerを実現)
         * public static Object newProxyInstance(ClassLoader loader,
 Class[] interfaces,
 InvocationHandler h)
         */
        return Proxy.newProxyInstance(proxyObject.getClass().getClassLoader(),
                proxyObject.getClass().getInterfaces(), this);
    }
呼び出したnewProxyInstanceメソッド
 public static Object newProxyInstance(ClassLoader loader,
					  Class<?>[] interfaces,
					  InvocationHandler h)
	throws IllegalArgumentException
    {
	if (h == null) {
	    throw new NullPointerException();
	}

	/*
	 * Look up or generate the designated proxy class.
	 */
	Class cl = getProxyClass(loader, interfaces);  // $Proxy0 

	/*
	 * Invoke its constructor with the designated invocation handler.
	 */
	try {
	    Constructor cons = cl.getConstructor(constructorParams);
	    return (Object) cons.newInstance(new Object[] { h });
	} catch (NoSuchMethodException e) {
	    throw new InternalError(e.toString());
	} catch (IllegalAccessException e) {
	    throw new InternalError(e.toString());
	} catch (InstantiationException e) {
	    throw new InternalError(e.toString());
	} catch (InvocationTargetException e) {
	    throw new InternalError(e.toString());
	}
    }

getProxyClass()メソッドは長く、直接JDKソースを開いて理解を学ぶことができます
 $Proxy0 
/** prefix for all proxy class names */
    private final static String proxyClassNamePrefix = "$Proxy";
    
    String proxyName = proxyPkg + proxyClassNamePrefix + num;
		/*
		 * Verify that the class loader hasn't already
		 * defined a class with the chosen name.
		 */

		/*
		 * Generate the specified proxy class.
		 */
		byte[] proxyClassFile =	ProxyGenerator.generateProxyClass(
		    proxyName, interfaces);
		try {
		    proxyClass = defineClass0(loader, proxyName,
			proxyClassFile, 0, proxyClassFile.length);

$Proxy 0クラスはinterfacesのインタフェースを実現し、Proxyクラスを継承します.
クラスローダで動的に作成された$Proxy 0
public final class $Proxy0 extends Proxy implements ProxyInterface{  
    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("java.lang.Object").getMethod("toString",  
                    new Class[0]);  
             m2 = Class.forName(" com.atb.proxy.simple.ProxyImple").getMethod("methodPrint",  
                    new Class[0]);  
  
        } catch (NoSuchMethodException nosuchmethodexception) {  
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
        } catch (ClassNotFoundException classnotfoundexception) {  
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
        }  
    } //static  
  
    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 methodPrint() {  
        try {  
            super.h.invoke(this, m2, null);  
            return;  
        } catch (Error e) {  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final String toString() {  
        try {  
            return (String) super.h.invoke(this, m3, null);  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
}

newProxyInstanceメソッドを続行します
 Constructor cons = cl.getConstructor(constructorParams); // 
  return (Object) cons.newInstance(new Object[] { h }); //   
  
   
  class Proxy{  
    InvocationHandler h=null;  
    protected Proxy(InvocationHandler h) {  
        this.h = h;  
    }  
    
}

まとめ:実装されたInvocationHandlerインタフェースinvokeはいつ呼び出されるのか
public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = method.invoke(proxyObject, args);
		return result;
	}

$Proxy 0インスタンス--』ProxyInterfaceは、ProxyInterfaceに参照を割り当てます.ProxyInterfaceメソッドを実行する場合、$Proxy 0クラスのmethodPrint()メソッドが呼び出され、さらに親クラスProxyのhのinvoke()メソッドが呼び出される.つまりInvocationHandler.invoke().