JDK动态代理的底层实现原理
动态代理是许多框架底层实现的基础,比如Spirng的AOP等,其实弄清楚了动态代理的实现原理,它就没那么神奇了,下面就来通过案例和分析JDK底层源码来揭秘她的神秘面纱,让她一丝不挂地呈现在我们面前,邪恶了。。。
代理模式定义
存在一个代理对象,并且这个代理对象持有真实对象的引用,以实现对真实对象的访问控制。
举个例子,现在公司一般都有VPN,使我们在家也能访问到公司的内网(比如连接公司的数据库等),实现居家办公。这里VPN相当于一个代理,而公司内网相当于被代理对象,也就是真实对象。我们不能直接访问公司内网(真实对象),但是我们通过VPN(代理对象),输入身份信息,确认无误后就可以访问到公司内网。这就是代理模式的作用----控制对象的访问。
代理模式的分类
静态代理
该代理对象持有被代理对象的引用,客户端通过调用代理对象的方法间接实现调用真实对象的方法。代理对象可以在调用真实对象的方法前面加入一些操作:比如身份验证,如果身份验证没有通过,则不能访问真实对象的方法,否则可以调用真实对象的方法;也可以在调用真实对象方法后,加入一些操作,比如记录访问日志。
真实对象接口,提供两个服务方法
/**
*
* People 真实对象的接口包含两个方法
*
* @author: tanggao
* @date::2017-9-27 下午3:57:20
* @version 1.0
*/
public interface People {
voidsayHello(String msg);
voidsayBye(String msg);
}
真实对象接口的具体实现
/**
*
*Student
* 真实对象接口的实现
*@author: tanggao
*@date::2017-9-27 下午3:58:05
*@version 1.0
*/
public class Student implements People {
@Override
public void sayHello(String msg) {
System.out.println("Hello "+msg);
}
@Override
public void sayBye(String msg) {
System.out.println("ByeBye "+msg);
}
}
代理对象:
/**
*
*StaticProxy
* 代理对象,控制对真实对象的访问控制
*@author: tanggao
*@date::2017-9-27 下午4:01:03
*@version 1.0
*/
public class StaticProxy implements People {
//真实对象,客户端不能直接访问
private Peoplepeople;
publicStaticProxy(){
this.people=new Student();
}
@Override
public void sayHello(String msg) {
booleanfriendFlag=true;
if(friendFlag){
people.sayHello(msg);
}
System.out.println("记录访问日志");
}
@Override
public void sayBye(String msg) {
booleanfriendFlag=true;
if(friendFlag){
people.sayBye(msg);
}
System.out.println("记录访问日志");
}
}
客户端调用及结果:
上面就是静态代理的一个实现,通过静态代理,实现了访问控制,但是在每个真实对象方法之前都加入了访问控制代码来验证权限。如果有很多个方法,则要在每个方法调用前都加入验证权限的代码,这样非常的不灵活且有大量的重复代码,即使把验证权限抽象出来做过方法或者类,但是还是得在每个方法前加一段调用权限验证的代码,比如,一个客户端只用其中的一个方法,但是代理中两个方法都要加入权限控制,要满足其他客户端的调用需求,上面接口中只有两个方法还好,但是如果有上百个方法那岂不是很臃肿。那么有什么办法解决了,那就是动态代理
动态代理
动态的生成代理类,而不用像静态代理一样,在编译期间进行定义类。动态代理更加灵活,不用显示的在所有方法前面或者后面加入权限验证、记录日志等操作。
动态代理的实现如下:
其中真实对象接口和它的实现