JDK的动态代理,就是在程序运行的过程中,根据被代理的接口来动态生成代理类的class文件,并加载运行的过程。下面我们看一个示例:
/**
定义一个Animal接口
**/
public interface Animal {
void eat();
}
/**
定义一个Animal接口的实现类Cat
**/
public class Cat implements Animal {
public void eat() {
System.out.println(“Cat eat”);
}
}
/**
定义一个InvocationHandler接口的实现类AnimalInvocationHandler
**/
public class AnimalInvocationHandler implements InvocationHandler {
private Object mProxy;
public AnimalInvocationHandler(Object object){
mProxy = object;
}
/**
* 通过Proxy.newProxyInstance方法生产动态代理类
* @return
*/
public Object getProxy(){
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), mProxy.getClass().getInterfaces(), this);
}
/**
* 掉用被代理类的接口方法最终会掉用invoke方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("----- before -----");
Object result = method.invoke(mProxy, args);
System.out.println("----- after -----");
return result;
}
}
/**
测试类
**/
public class Main {
public static void main(String[] args) throws Exception{
Animal animal = new Cat();
AnimalInvocationHandler animalInvocationHandler = new AnimalInvocationHandler(animal);
Animal proxy = (Animal)animalInvocationHandler.getProxy();
proxy.eat();
createProxyClassFile();
}
/**
* 将动态生产的代理类class文件保存下来
*/
public static void createProxyClassFile()
{
String name = "ProxySubject";
byte[] data = ProxyGenerator.generateProxyClass( name, new Class[] { Animal.class } );
try
{
FileOutputStream out = new FileOutputStream( name + ".class" );
out.write( data );
out.close();
}
catch( Exception e )
{
e.printStackTrace();
}
}
}
运行main方法我们可以看到当掉用Animal proxy = (Animal)animalInvocationHandler.getProxy();
proxy.eat();
最终掉用的是AnimalInvocationHandler类中的invoke方法。
WHY?我们可以看下保存下来的动态生成类的class 代码:
public final class ProxySubject extends Proxy implements Animal
{
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public ProxySubject(InvocationHandler paramInvocationHandler)
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void eat()
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName(“java.lang.Object”).getMethod(“equals”, new Class[] { Class.forName(“java.lang.Object”) });
m3 = Class.forName(“com.zld.dynamicproxy.Animal”).getMethod(“eat”, new Class[0]);
m2 = Class.forName(“java.lang.Object”).getMethod(“toString”, new Class[0]);
m0 = Class.forName(“java.lang.Object”).getMethod(“hashCode”, new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
可以看到该类继承自Proxy并实现了Animal接口,在看下该类的eat方法就明白了为什么会掉用AnimalInvocationHandler类的invoke方法。
PS(ProxyGenerator类的导入可以通过点击右边的Add》打开access rules设置》选择resolution为accessible》按照提示在下面的rule pattern输入相应的pattern;
pattern 可以输入* 代表所有的包均可导入 ,也可以输入相应包路径下面的类可以进入访问,例如sun/misc/*等等;)