java 动态代理高级

从JDK1.3以后,java引入动态代理机制,即对目标对象的方法调用是通过代理对象来完成的,java的动态代理只能针对接口进行动态代理,即要实现动态代理的类必须实现接口,CGLIB提供了针对类的动态代理功能。JDK动态代理的例子如下:

//代理接口  
package com.proxy.test;

interface IProxy{  
    public void hello(String s);  
}  
//接口实现类,即被代理类  
class ProxyImpl implements IProxy {  
    public void hello(String s){  
        System.out.println(“Hello, ” + s);  
    }  
}   
//动态代理处理类  
class ProxyHandler implements InvocationHandler{  
    //代理实现类  
    private Object delegate;              
    public ProxyHandler (Object obj) {      
            delegate = obj;      
        }      
    public Object invoke(Object proxy, Method method, Object[] args){  
        System.out.println(“Before mothod:” + method);  
        Object result = method.invoke(this.delegate, args);   
        System.out.println(“After mothod:” + method);  
        return result;   
    }  
}  
public class DynamicProxyDemo{  
    public static void main(String[] args){  
        IProxy p = new ProxyImpl();  
        ProxyHandler handler = new ProxyHandler(p);  
        //产生动态代理  
    IProxy  proxy = (IProxy)Proxy.newProxyInstance(IProxy.class.getClassLoader(), p.getClass().getInterfaces(), handler);  
        proxy.hello(“world”);  
    }  
}  

输出结果:

Before mothod:hello

Hello, world

After mothod:hello

相信很多人都会写上面的动态代理,但是很多人对下面的问题感觉迷惑不解:

(1).InvocationHandler的public Object invoke(Object proxy, Method method, Object[] args)方法中proxy参数并没有在方法体内使用,这个参数到底被谁使用?

这个问题比较好回答,proxy虽然没有在invoke方法体内使用,但是这个参数就是Proxy.newProxyInstance方法产生的动态代理对象,通过这个代理对象做如下两件事:

a.在调用目标对象之前/之后首先调用InvocationHandler的Invoke方法。

b.代理对象调用目标对象的目标方法。

(2).Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)方法究竟做了什么事?

Proxy.newProxyInstance方法返回了一个实现代理接口,并且代理了目标方法实例行为的对象,通过JDK中sun.misc.ProxyGenerator.generateProxyClass()方法操作字节码完成以下几件事.
a.根据类加载器参数loader和代理接口interfaces调用方法 getProxyClass(loader, interfaces)创建代理类$Proxy.
$Proxy0类实现了interfaces的接口,并继承了Proxy类.
b.实例化$Proxy0并在构造方法中把实现了InvocationHandler接口的代理处理器对象传给父类Proxy,接着$Proxy0调用父类Proxy的构造器,为h赋值。

在程序中通过System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”,“ture”);设置java虚拟机系统属性,在运行程序的过程中会生成$Proxy0.class文件,使用反编译工具反编译之后代码如下:

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 IProxy {
private static Method m0;
private static Method m1;
private static Method m2;
private static Method m3;

static {
   try {
   //通过反射机制获取Object中的hashCode(), equals()和toString()方法
   m0 = Class.forName("java.lang.Object").getMethod("hashCode",
          new Class[0]);
    m1 = Class.forName("java.lang.Object").getMethod("equals",
          new Class[] { Class.forName("java.lang.Object") });
    m2 = Class.forName("java.lang.Object").getMethod("toString",
          new Class[0]);
   //获取代理接口Proxy的代理方法hello
      m3 = Class.forName("com.proxy.test.IProxy").getMethod("hello",
            new Class[0]);
      } catch (NoSuchMethodException nosuchmethodexception) {
       throw new NoSuchMethodError(nosuchmethodexception.getMessage());
   } catch (ClassNotFoundException classnotfoundexception) {
       throw new NoClassDefFoundError(classnotfoundexception.getMessage());
   }
}
//将实现了InvocationHandler接口的对象传递给父类Proxy
public $Proxy0(InvocationHandler invocationhandler) {
   super(invocationhandler);
}
//代理hashCode()方法
@Override
public final int hashCode() {
   try {
    return ((Integer) super.h.invoke(this, m0, null)).intValue();
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
//代理equals()方法
@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);
   }
}
//代理toString()方法
@Override
public final String toString() {
   try {
    return (String) super.h.invoke(this, m2, null);
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
//代理接口中的代理方法
public final void hello() {
   try {
    super.h.invoke(this, m3, null);
    return;
   } catch (Error e) {
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
}
当执行 proxy.hello() 方法时 , 就调用了 $Proxy0 类中的 hello() 方法 .
hello 方法中 , 调用父类 Proxy 中的 h invoke() 方法,即 InvocationHandler.invoke(); 方法。

你可能感兴趣的:(java,object,equals,Class,反编译工具)