Java静态代理和动态代理(一)

2014-11-24 07:42:57 · 作者: · 浏览: 0
  今天介绍一下代理设计模式,在业务场景中使用代理模式的好处有很多,包括什么权限校验,事务管理等等,具体有什么好处大家自动百度吧,我这里只解释代理模式的设计原理。首先这个设计模式出来的时候先是静态代理模式,只有理解了静态代理模式,才能理解JDK提供的动态代理是怎么回事,首先介绍静态代理,如果有错误的地方请大家不要拍砖,请大家指正。  
    一,静态代理 
    第一种情况:假如我去租房,没有经过中介,直接找到了房屋的主人。这里抽象一下就是我直接访问了真实对象(房屋的主人),然后我把房屋给租了。
    第二种情况:假如我去租房,需要经过中介,找到一家租房的中介公司,然后把房屋租了。这里抽象一下就是我访问了真实对象的代理对象(中介),这里的代理对象(中介)需要持有真实对象(房屋主人)才能把房屋租给我(因为中介手里没有房子,他肯定要有房屋真实主人的房子才行)。结构图如下:
           
     
    大家一定要明白的是,代理对象(中介)一定要持有真实对象(房屋主人)才行。
    下边是静态代理的代码实现:
    首先代理对象和真实对象都需要实现同一个接口或继承抽象类,这个接口或者抽象类其实就是说我这里是租房屋的,不是租汽车的或别的东西,接口中定义一个quote(报价)方法。   
public interface Subject {
/***
* 这个接口定义一个报价方法
*/
public String quote();
}
    然后定义一个真实对象类,就是代表真实的房屋的主人,实现Subject接口,同时实现报价方法:
public class RealSubject implements Subject {
@Override
public String quote() {
return "房屋出租2000元一个月";
}
}
    定义一个代理类,这个代理类一定持有真实对象的引用
public class ProxySubject implements Subject{
@Override
public String quote() {
//代理对象持有真实对象
Subject subject = new RealSubject();
//返回真实对象的报价多少钱
String quote = subject.quote();
//代理对象增加真实对象的报价
return quote.replace("2000", "3000");
}
}
  编写我们的测试类,租房去找中介,然后查看房屋的报价是多少钱
public static void main(String[] args) {
/**
* 代理对象和真实对象都要实现同一个接口
*/
//直接访问真实对象
Subject subject = new RealSubject();
System.out.println(subject.quote());
//访问代理对象
subject = new ProxySubject();
System.out.println(subject.quote());
}
    执行之后会发现中介把房屋的租金增加了,这就起到了代理的作用。这就是一个静态代理的小例子,静态代理主要注意两点:1,真实类和代理类都实现一个相同的接口;2,代理类持有真实类的对象的引用。按照租房的情况说明就是:中介和房租主人都必须是卖房子的,不能你去中介租房,结果给你返回一个汽车的报价;中介必须有房屋主人的房子才能租给你,如果中介手中没有房子,只是一个空壳子,也没有办法把房子租给你。
    静态代理的一个不好的地方是如果接口里增加了一个方法,那么真实类和代理类都必须实现相应的方法,增加了代码的复杂程度。还有就是如果代理类没有实现接口怎么办(解决办法自行百度吧 ^_^)
    二,动态代理
    JDK提供了一个java.lang.reflect.Proxy对象,可以用来对真实类实现动态代理,在运行时通过反射增强真实类。我们这里给Subject接口增加一个方法 getHouseAddress(得到房子的地址),然后真实类实现这个方法,返回"房屋的地址在地球";代码如下:
    
public class RealSubjectHome implements Subject{
@Override
public String quote() {
return "房屋出租2000元";
}
@Override
public String getHouseAddress() {
return "房屋的地址在地球";
}
}
    这里我们看一下代理类的实现(主要的解释都在注释中):
public final class DynamicProxy implements InvocationHandler{
//代理对象是要持有真实对象
private Object RealObject;
public Object createSubject(Object RealObject){
/**
* 参数含义:
* classloader 是代理的类加载器
* interface 就是代理类实现的接口,因为代理类需要和真实对象实现相同的接口,所以返回的就是真实类的接口
* InvocationHandler 调用真实类的处理函数,代理类需要对真实对象做一些处理
* 返回值 返回一个真实类的代理对象
*
*/
this.RealObject = RealObject;
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
this.RealObject.getClass().getInterfaces(), //这里是真实对象实现的接口,代理对象也要实现相同的接口
this);
}
/**
* 参数:
* proxy 就是代理类的对象
* method 就是需要调用的实现接口中的方法
* args 方法中的参数
* 返回值 返回代理类调用实现接口的方法的返回值
*/
@Override
public Object invoke(Obje