JDK动态代理
jdk动态代理必须借助一个接口才能产生代理对象,所以先定义接口
public interface ProxyExInterface {
public void sayHelly();
public void sayHelly2();
}
然后提供接口实现类
public class ProxyImpl implements ProxyExInterface {
@Override
public void sayHelly() {
// TODO Auto-generated method stub
System.out.println("sayHelly");
}
@Override
public void sayHelly2() {
// TODO Auto-generated method stub
System.out.println("sayHelly2");
}
}
在jdk动态代理中,要实现代理逻辑的类必须实现invocationHandler 接口,它里面定义了一个invoke 方法
建立代理关系分为两个步骤:1,先要建立起代理对象和真实服务对象的关系,2,然后实现代理逻辑,在invoke方法中可以实现代理逻辑。
public class ProxyClassEX implements InvocationHandler {
//真实对象
Object tob=null;
//建立代理关系,返回代理对象
public Object bind(Object old){
this.tob=old;//这就是存下真是对象
Object tt=Proxy.newProxyInstance(old.getClass().getClassLoader(), old.getClass().getInterfaces(),this);
//看看返回的是否是Proxy类对象
System.out.print(tt instanceof Proxy);
return tt;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.print("前");
Object nob=method.invoke(tob, args);
System.out.print("后");//代理结果返回
return nob;
}
}
建立并生成代理对象的主要代码是:
Proxy.newProxyInstance(old.getClass().getClassLoader(), old.getClass().getInterfaces(),this);
此方法的第一个参数是类加载器,第二个参数是把生成的动态代理对象下挂带哪些接口下,第三个参数是实现 方法逻辑的代理类,本列就是this 自身。
在invoke方法中 method.invoke(tob, args); 是调用真实对象。
测试jdk 动态代理
public class CS {
public static void main(String[] args) {
// TODO Auto-generated method stub
ProxyClassEX ex=new ProxyClassEX();
ProxyExInterface pf=(ProxyExInterface)ex.bind(new ProxyImpl());
pf.sayHelly();
pf.sayHelly2();
}
}
测试输出结果:
true
前
sayHelly
后
前
sayHelly2
后
疑问:每次调用ProxyExInterface 方法时,为什么会执行ProxyClassEX 的invoke方法?
在实现代理逻辑类的bind 方法中,有这么一句代码:
System.out.print(tt instanceof Proxy);通过测试我们知道他的结果返回为true,那么说明Proxy.newProxyInstance 返回的是Proxy的对象,其实起作用的是$Proxy0 类,
我们在main方法首句加入,下面代码
/* 设置此系统属性,让JVM生成的Proxy类写入文件.保存路径为:com/sun/proxy(如果不存在请手工创建) */
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
然后在工程跟目录建立 com.sun.proxy 文件路径,如图。然后重新执行
然后在我们工程目录就可以找到代理生成的类$Proxy0
$Proxy0 继承了Proxy 实现了ProxyExInterface,而Proxy 有全局变量 protected InvocationHandler h;
$Proxy0 生成的代码主要如下:
由此可以看到:当执行sysHelly2方法时,会调用InvocationHandler 的invoke 方法。
参照博客:https://blog.csdn.net/chenzhiqin20/article/details/50900439
参照书籍:《互联网轻量级框架整合开发》2.2.1 JDK动态代理