再讲java动态代理前,先来看看代理模式。
Proxy类通过组合,对Hello类进行了增强,并对其进行了委托。
代理模式代码:
public class ProxyPattern {
interface IHello{
void say() ;
}
static class Hello implements IHello{
public void say(){
System.out.println("hello world");
}
}
static class Proxy implements IHello{
IHello iHello ;
public Proxy(IHello hello){
iHello = hello ;
}
@Override
public void say() {
System.out.println("this is proxy"); //对Hello类进行了增强
iHello.say() ;
}
}
public static void main(String[] args) {
IHello hello = new Hello() ;
IHello proxy = new Proxy(hello) ;
proxy.say() ; // 代理类实现了实现类的委托,并对实现类进行了增强。
}
}
下面讲讲动态代理:
动态代理类DynamicProxy没有直接去写一个Proxy类,而是通过实现InvocationHandler接口。在bind()方法中通过IHello接口,类加载器,调用Proxy.newProxyInstance()方法去动态生成$Proxy0的字节码,通过jad反编译可以得到$Proxy0类,所以将Proxy.newProxyInstance()代码换成new $Proxy0(this); 也是同样的效果。此时通过bind方法得到了$Proxy0类,在invoke方法中对其进行增强,再通过$Proxy0的反射机制调用到Hello类的say方法(因为ProxyDynamic实现了IHello接口,所以在bind方法时生成的$Proxy0类也实现了IHello接口,这样便可以通过反射机制调用到Hello类的say方法),实现了代理模式。
动态代理代码:
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;
public class DynamicProxyTest {
interface IHello{
void say() ;
}
static class Hello implements IHello{
public void say(){
System.out.println("hello world");
}
}
static class DynamicProxy implements InvocationHandler{
Object obj ;
Object bind(Object obj){
this.obj = obj ;
System.out.println("获取ihello接口");
// return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
// 通过接口,实现类,生成代理类的字节码 ,反编译后就是$Proxy0类
return new $Proxy0(this); // 等价上面那句,意思便是生成一个代理类。
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("welcome");
return method.invoke(obj, args);
// 从$Proxy0类中的say()方法中调用此invoke() 方法,传入的method方法正是Hello类的say()方法,通过反射机制调用Hello类的say()方法。
}
}
public static void main(String[] args) {
Field field;
try {
field = System.class.getDeclaredField("props");
field.setAccessible(true);
Properties props = (Properties) field.get(null);
props.put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
} catch (Exception e) {
e.printStackTrace();
}
// new DynamicProxy().bind(new Hello()) 其实是$proxy0类,实现Ihello类
IHello ihello = (IHello)new DynamicProxy().bind(new Hello());
ihello.say() ;
}
}
动态代理生成的字节码通过反编译而得到的$Proxy0类,它是通过Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);生成的字节码。
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3)
import java.lang.reflect.*;
public final class $Proxy0 extends Proxy
implements DynamicProxyTest.IHello{
public $Proxy0(InvocationHandler invocationhandler){
super(invocationhandler);
}
public final void say(){
try
{
super.h.invoke(this, m3, null);
// 调用InvocationHandler实现类的invoke方法,实现代理模式;并通过反射机制调用m3方法,即Hello类的say()方法。
return;
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final boolean equals(Object obj)
{
try
{
return ((Boolean)super.h.invoke(this, m1, new Object[] {
obj
})).booleanValue();
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
return false;
}
public final int hashCode()
{
try
{
return ((Integer)super.h.invoke(this, m0, null)).intValue();
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
return 0;
}
public final String toString()
{
try
{
return (String)super.h.invoke(this, m2, null);
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
return null;
}
private static Method m3;
private static Method m1;
private static Method m0;
private static Method m2;
static
{
try
{
m3 = Class.forName("DynamicProxyTest$IHello").getMethod("say", new Class[0]);
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]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
}
catch(NoSuchMethodException nosuchmethodexception)
{
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
}
catch(ClassNotFoundException classnotfoundexception)
{
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
}
未完待续。。。后面将加上如何生成字节码的学习。