首页 > 代码库 > java 动态代理的学习详解

java 动态代理的学习详解

再讲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());

        }

    }

}

未完待续。。。后面将加上如何生成字节码的学习。

java 动态代理的学习详解