动态代理类的实现和源码解析
1.动态代理的实现
- 首先定义一个接口
public interface Message {
String hello(String str);
String bye();
}
- 创建被代理的类
public class RespnnseMessage implements Message {
@Override
public String hello(String str) { return "hello" + str; }
@Override
public String bye() { return "see you tomorrow"; }
}
- 创建InvocationHandlerTest,这个类实现了InvocationHandler接口,并持有一个被代理类的对象,InvocationHandler中有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法。然后通过反射在invoke方法中执行代理类的方法。
public class InvocationHandlerTest<T> implements InvocationHandler {
//被代理的对象
private T object;
public InvocationHandlerTest(T object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
//通过反射执行被代理对象的方法 object是被代理的对象,args 是被代理对象的方法参数
//method是被代理对象的方法
Object obj = method.invoke(object, args);
System.out.println(obj.toString());
System.out.println("after");
return obj;
}
}
- 创建动态代理对象
public class ProxyClient {
public static void main(String[] args) {
//被代理的实例对象
Message message = new RespnnseMessage();
//创建InvocationHandler
InvocationHandlerTest invocationHandlerTest = new InvocationHandlerTest(message);
//创建动态代理对象
Message message1 = (Message) Proxy.newProxyInstance(invocationHandlerTest.getClass().getClassLoader(),
message.getClass().getInterfaces(), invocationHandlerTest);
//动态代理对象调用方法
message1.hello("你好");
message1.bye();
}
}
- 执行结果
before
hello你好
after
before
see you tomorrow
after
2.源码分析
- 查看Proxy.newProxyInstance源码,通过反射获取动态代理对象的有参构造方法,然后通过有参构造方法和反射来获取动态代理的对象。主要代码已经注释
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
//生成动态代理类 $Proxy0
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//调用动态代理类$Proxy0的public的有参构造方法,参数类型是InvocationHandler.class
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//通过构造方法实例化动态代理类的实例对象 h 是InvocationHandlerTest类
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
- 查看动态代理类源码
- Class<?> cl = getProxyClass0(loader, intfs); 生成了动态代理类,我们通过下面代码生成动态代理类的源码。
byte[] classByte = ProxyGenerator.generateProxyClass("$Proxy0",
new Class<?>[] { Message.class });
String path = "D:\\testdata\\$Proxy0.class";
try (FileOutputStream fos = new FileOutputStream(path)) {
fos.write(classByte);
fos.flush();
} catch (Exception e) {
e.printStackTrace();
}
- 将生成的$Proxy0 Class反编译查看源码
//动态代理类继承了extends并实现了Message自定义接口的方法
public final class $Proxy0 extends Proxy implements Message {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m4;
private static Method m0;
//动态代理类 cons.newInstance(new Object[]{h}); 会通过反射实例化对象调用父类的有参构造函数
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 bye() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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 String hello(String var1) throws {
try {
//调用InvocationHandlerTest的invoke方法 m4 是被代理类的方法,var1 被代理类的参数
return (String)super.h.invoke(this, m4, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
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"));
m3 = Class.forName("DynamicProxy.Message").getMethod("bye");
m2 = Class.forName("java.lang.Object").getMethod("toString");
//通过反射获取到被代理类的方法
m4 = Class.forName("DynamicProxy.Message").getMethod("hello", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
通过源码我们发现 p r o x y 0 继承了 P r o x y ,当通过上面的 c o n s . n e w I n s t a n c e ( n e w O b j e c t [ ] h ) ; 后 proxy0继承了Proxy,当通过上面的 cons.newInstance(new Object[]{h});后 proxy0继承了Proxy,当通过上面的cons.newInstance(newObject[]h);后Proxy0会调用自己的有参构造方法,从而调用父类Proxy的有参构造方法,父类的Proxy的部分源码如下:
protected InvocationHandler h;
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
可以看出这里面的h就是我们继承InvocationHandler的自定义类InvocationHandlerTest这个类,当动态代理的对象调用hello(“你好”)这个方法,其实调用的是return (String)super.h.invoke(this, m4, new Object[]{var1}),也即是调用InvocationHandlerTest这个类的invoke方法。然后就会调用被代理类的invoke()方法,最终执行被代理类的方法。