1. jdk 动态代理基本使用
1 2 3
| public interface Subscribe { void subscrib(); }
|
1 2 3 4 5 6
| public class SubImpl implements Subscribe { @Override public void subscrib() { System.out.println("subscribe invoked "); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class SubHandler implements InvocationHandler {
private Object realObj;
public SubHandler(Object realObj) { this.realObj = realObj; }
@Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if (method.getDeclaringClass() == Object.class) { return method.invoke(o,objects); }
System.out.println("before invoked ");
Object invoke = method.invoke(realObj, objects);
System.out.println("after invoked ");
return invoke; } }
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class MyClass {
public static void main(String[] args) {
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
Subscribe subscribe = new SubImpl();
Subscribe proxy = (Subscribe) Proxy.newProxyInstance(subscribe.getClass().getClassLoader(), subscribe.getClass().getInterfaces(), new SubHandler(subscribe));
proxy.subscrib(); }
}
|
以上代码是对于jdk动态代理的基本使用。值得注意的是,jdk的动态代理类, 必须是有接口的。
执行结果如下:
before invoked
subscribe invoked
after invoked
2. 源码分析
1 2
| Subscribe proxy = (Subscribe) Proxy.newProxyInstance(subscribe.getClass().getClassLoader(), subscribe.getClass().getInterfaces(), new SubHandler(subscribe));
|
通过对于proxy类进行打印发现,他的父类其实是 java.lang.reflect.Proxy
下面我们具体分析,我们的 proxy对象是怎么生成的
1. 首先进入Proxy.newProxyInstance静态方法.鉴于代码篇幅较长,做了一部分删减。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { ...... /* * Look up or generate the designated proxy class. */ Class<?> cl = getProxyClass0(loader, intfs);
final Constructor<?> cons = cl.getConstructor(constructorParams); .......
return cons.newInstance(new Object[]{h}); }
|
通过以上代码,我们发现关键点 在这里主要做了三件事
1. 通过 getProxyClass0 方法获取 Class对象
2. 调用默认构造方法 conns
3. 通过构造方法生成我们需要的返回对象
这里我们再次进入getProxyClass0 看如何生成 class对象的。
跟进代码进入到 ProxyClassFactory.apply 方法
1 2 3 4 5 6 7 8 9 10 11
| byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { return defineClass0(loader, proxyName, proxyClassFile, 0,proxyClassFile.length); } catch (ClassFormatError e) { }
|
首先通过 ProxyGenerator.generateProxyClass生成字节码的数组,然后通过
defineClass0 生成class对象。 defineClass0是native方法。
到目前为止,我们就完成了整个流程的分析。
3. 我们通过Proxy.newProxyInstance类内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| public final class $Proxy0 extends Proxy implements Subscribe { private static Method m1; private static Method m2; private static Method m3; private static Method m0;
public $Proxy0(InvocationHandler var1) throws { super(var1); }
public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } }
public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }
public final void subscrib() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }
public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }
static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("com.example.lib.Subscribe").getMethod("subscrib"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
|
以上是我们通过动态代理生成的类,继承了 Proxy,实现我们的Subscribe接口
默认实现了object中的 equals,toString,hashCode方法
以及Subscribe接口中的方法
以上方法提的人内容大同小异,通过静态代码块实例化的method,最后调用我们的
handler的invoke方法