动态代理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("\n"+"ProxyInterface--->($Proxy0)中的方法有:");  
        Method[] method=proxyInter.getClass().getDeclaredMethods();  
        for(Method m:method){  
            System.out.print(m.getName()+", ");  
        }  
        System.out.println("\n"+"ProxyInterface ($Proxy0)的父类是:"+proxyInter.getClass().getSuperclass());  
        System.out.print("\n"+"ProxyInterface ($Proxy0)实现的接口是:");  
          
        Class<?>[] interfaces=proxyInter.getClass().getInterfaces();  
          
        for(Class<?> i:interfaces){  
            System.out.print(i.getName()+", ");  
        }  
        System.out.println("\n"+"#调用的结果:");
        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 $Proxy0  从这里可以看出

     ProxyInterface proxyInter=(ProxyInterface)proxy.bind(new ProxyImple());

     返回的Class 居然是$Proxy0  并不是 接口实现ProxyImple 的字节码,以前我一直理解是ProxyImple的实例去调用它的方法methodPrint();其实它是通过类加载器动态的构造了$Proxy0 的对象,我们控制台打印可以看出

ProxyInterface--->($Proxy0)中的方法有:equals, toString, hashCode, methodPrint,   

ProxyInterface ($Proxy0)的父类是:class java.lang.reflect.Proxy


$Proxy0 是在什么时候构造出来的呢打开  

    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);

    }

  调用的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);

$Proxy0类 实现了interfaces的接口,并继承了Proxy类

类加载器动态创建的$Proxy0

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;
	}

$Proxy0实例---》ProxyInterface,将引用赋给ProxyInterface。执行ProxyInterface方法时,调用了$Proxy0类中的methodPrint()方法,进而调用父类Proxy中的h的invoke()方法.即InvocationHandler.invoke()。 




   





你可能感兴趣的:(proxy,invoke,invoke到底什么时候调用)