一:使用例子
public class ProxyDemo implements InvocationHandler {
static ProxyDemo proxyDemo = new ProxyDemo();
public ProxyDemo() {
}
private Object sub;
public ProxyDemo(Object obj) {
sub = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("被調用代理對象的方法: " + method.getName() + ":" + method.getDeclaringClass());
System.out.println("before method !!!!!");
Object invoke = method.invoke(sub, args);
System.out.println("after method !!!!!");
return invoke;
}
public <T> T getProxy(T t) {
ProxyDemo handler = new ProxyDemo(t);
return (T) Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), handler);
}
public static void main(String[] args) {
PersonDao pDao = new PersonDaoImpl();
PersonDao proxy = proxyDemo.getProxy(pDao);
proxy.say();
System.out.println("完成");
}
}
interface PersonDao {
void say();
}
class PersonDaoImpl implements PersonDao {
@Override
public void say() {
System.out.println("hello boy");
}
}
二:代碼流程跟蹤,找到使用接口的位置
三:最終通過ProxyGenrator的generateProxyClass方法,使用接口Class生成代理的byte[],保存字節碼信息到class文件,idea打開並查看文件
public static void main(String[] args) {
Class<?>[] interfaces = new Class[]{PersonDao.class};
// 獲取代理字節碼文件,
byte[] bytes = ProxyGenerator.generateProxyClass("PersonDao", interfaces);
File file = new File("./jdk/src/main/java/javaDemo/proxyDemo/PersonDao.class");
try {
OutputStream outputStream = new FileOutputStream(file);
outputStream.write(bytes);
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
PersonDao.class文件,可以看到代理類繼承了Proxy,調用sya方法會執行super.h.invoke,並實現了傳入的接口,因爲所有生成的代理類的父類爲Proxy,Java類繼承機制不允許多重繼承,所以被代理類必須實現接口。並且實驗的過程證明了可以對final的方法和類進行代理,知道滿足接口實現即可。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import javaDemo.proxyDemo.PersonDao;
public final class PersonDao$Proxy extends Proxy implements PersonDao {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public PersonDao$Proxy(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 say() 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("javaDemo.proxyDemo.PersonDao").getMethod("say");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}