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 文件路径,如图。然后重新执行

JDK动态代理

然后在我们工程目录就可以找到代理生成的类$Proxy0 

JDK动态代理


$Proxy0 继承了Proxy 实现了ProxyExInterface,而Proxy 有全局变量     protected InvocationHandler h;


$Proxy0  生成的代码主要如下:

JDK动态代理

由此可以看到:当执行sysHelly2方法时,会调用InvocationHandler 的invoke 方法。



参照博客:https://blog.csdn.net/chenzhiqin20/article/details/50900439

参照书籍:《互联网轻量级框架整合开发》2.2.1 JDK动态代理