最近复习了一下java动态代理
jdk中提供了java.lang.reflect.Proxy方法来为接口创建动态代理(Proxy只能为接口生成动态代理)
参与成员:
自己定义的接口类
接口类的实现类
定义一个类实现java.lang.reflect.InvocationHandler接口
,这个类应该有一个接口类的成员变量
实现invoke方法,做特定操作,并调用实际的接口类实现对象的方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("enter into " + method.getName()); Object result = null; if(method!=null){ result=method.invoke(foo,args) ; } System.out.println("exit the method"+method.getName()); return result; }
调用类
Foo newFoo= new FooImpl(10); LogInvocationHandler handler = new LogInvocationHandler(newFoo); Class<?>[] interfaces=new Class<?>[]{Foo.class}; Foo proxy= (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),interfaces,handler); proxy.add(2);proxy.调用方法newProxyInstance为接口创建一个动态的代理类产生这个类字节码的是sun.misc.ProxyGenerator类,通过调用其generateProxyClass来产生这个字节码
如果像查看运行过程中产生的类字节码需要设置System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");这样在com/sun/proxy下可以见到其字节码文件,使用jd-gui对其反编译,可以见到其所有的方法都是转调用handler的invoke方法public final class $Proxy0 extends Proxy implements Foo { private static Method m1; private static Method m5; private static Method m3; private static Method m2; private static Method m4; private static Method m0; public $Proxy0(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } public final boolean equals(Object paramObject) throws { 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 minus(int paramInt) throws { try { this.h.invoke(this, m5, new Object[] { Integer.valueOf(paramInt) }); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final void add(int paramInt) throws { try { this.h.invoke(this, m3, new Object[] { Integer.valueOf(paramInt) }); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final String toString() throws { 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 getValue() throws { try { return ((Integer)this.h.invoke(this, m4, null)).intValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int hashCode() throws { 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") }); m5 = Class.forName("*.Foo").getMethod("minus", new Class[] { Integer.TYPE }); m3 = Class.forName("*.Foo").getMethod("add", new Class[] { Integer.TYPE }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m4 = Class.forName("*.Foo").getMethod("getValue", 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()); } } }