public class DynamicProxy {
public interface IHello{
void sysHello();
}
static class IHelloImpl implements IHello{
@Override
public void sysHello() {
System.out.println("IHelloImpl#sysHello");
}
}
static class XXXDynamicProxy implements InvocationHandler{
private Object targetObject;
public <T> T bind(Object targetObject) {
this.targetObject = targetObject;
Object proxy = java.lang.reflect.Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this
);
return (T) proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before XXXDynamicProxy#invoke");
Object res = method.invoke(targetObject, args);
System.out.println("after XXXDynamicProxy#invoke");
return res;
}
}
public static void main(String[] args) {
// 保存动态产生的代理类的字节码到磁盘
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
IHelloImpl targetObject = new IHelloImpl();
IHello iHello = new XXXDynamicProxy().bind(targetObject);
iHello.sysHello();
}
}
java jdk自带的SDK动态代理,必须实现接口
cglib 可以实现没有实现接口类的代理
ASM可以实现字节码的修改
java.lang.reflect.Proxy.newProxyInstance 内部进行了验证、优化、缓存、同步、生成字节码、显示类加载等操作,最后调用了
sun.misc.ProxyGenerator.generateProxyClass 生成代理类的字节码【即 该API可以在运行的时候产生代理类的字节码】。