动态代理:在运行时再创建代理类和其实例。
举个栗子:
//抽象角色
interface Biz {
void print(String s);
}
//真实角色
public class BizImpl implements Biz{
@Override
public void print(String s) {
System.out.println("真实实现:" + s);
}
}
public class Test {
public static void main(String[] args){
BizImpl bizImpl = new BizImpl();
//动态代理
//第一个参数:类加载器
//第二个参数:想代理的接口类
//第三个参数:InvocationHandler是一个接口,会监听到Object o调用了print()方法,并把
//print()方法传递到invoke中,所以调用print()方法就会执行invoke()方法,args是print()对
//应的参数
Object o = Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{Biz.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(bizImpl, args);
}
});
Biz biz = (Biz)o;
biz.print("through proxy");
}
}
运行后得到打印:
真实实现:through proxy
调用o.print会调用invoke方法是因为newProxyInstance()方法会在内存中创建一个Class对象(具体方法在Proxy内部类的ProxyClassFactory里面),我们可以仿照它创建一个Class对象方便我们分析。我们在工程中新建一个module,类型选择java library(因为ProxyGenerator在sun.misc包下),命名为lib, 代码如下:
public class Test2 {
public static void main(String[] args){
String name = Biz.class.getName() + "$Proxy0";
//生成代理指定接口的Class数据
byte[] bytes = ProxyGenerator.generateProxyClass(name, new Class[]{Biz.class});
FileOutputStream fos;
try {
fos = new FileOutputStream("lib/" + name + ".class");
fos.write(bytes);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行后会在lib模块下生成类文件:Biz$Proxy0.class,代码如下:
public final class Biz$Proxy0 extends Proxy implements Biz {
private static Method m1;
private static Method m2;
private static Method m0;
private static Method m3;
public Biz$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 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);
}
}
public final void print(String var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m3 = Class.forName("com.enzo.lib.Biz").getMethod("print", Class.forName("java.lang.String"));
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
通过41-49行代码我们看到:调用print()方法会调用 super.h.invoke(this, m3, new Object[]{var1}),这里的super.h就是InvocationHandler接口,实际就是一个监听回调,这就是调用o.print会调用invoke方法的原因。



