首页 > 代码库 > Java反射学习总结三(静态代理)

Java反射学习总结三(静态代理)

反射最常见的应用就是代理模式了。

本文先简单介绍一下代理模式,并写一个静态代理的例子。为下一篇重要的动态代理做点铺垫


代理模式的作用是

为其他对象提供一种代理以控制对这个对象的访问。
另外在某些情况下,一个客户不想或着不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
说白了,代理模式就是一个"中介",他有这客户们的引用,所以可以用这个"中介"来代替客户来做操作。


代理模式设计的角色
想使用代理模式,需要定义如下的3个角色:

抽象角色

声明真实对象和代理对象的共同接口

真实对象

代理角色所代表的真实对象,是我们最终要引用的对象

代理角色: 

1.代理对象内部含有对真实对象的引用,从而可以操作真实的对象。
2.代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。
3.代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装


可能看完概念后有点迷糊,接下来直接上代码看例子应该会比较容易理解:

1.首先定义抽象角色对象,使用抽象类或者接口来定义一个代理角色和真实对象共有的一个方法。这个方法就是被代理角色委托给"中介"来操作的方法

[java] view plain copy print?技术分享技术分享
  1. //这里定义一个抽象类  
  2. public abstract class Subject {  
  3.     //空的抽象方法,这个方法需要代理角色和真实角色都去实现它  
  4.     public abstract void request();  
  5. }  


2.定义真实角色对象

[java] view plain copy print?技术分享技术分享
  1. //真实角色对象,继承自抽象角色,重写定义的方法。  
  2. public class RealSubject extends Subject{  
  3.   
  4.     //在重写的方法中实现需要的操作,这里只是简单打印一句  
  5.     @Override  
  6.     public void request() {  
  7.         System.out.println("this is real subject");  
  8.     }  
  9.   
  10. }  

 

3.定义代理角色对象

[java] view plain copy print?技术分享技术分享
  1. //代理角色,同样继承抽象角色,重写抽象角色中的方法  
  2. public class ProxySubject extends Subject{  
  3.     //在代理角色内部对真实角色的引用  
  4.     private RealSubject realSubject;      
  5.       
  6.     //重写的实现抽象角色中的方法  
  7.     @Override  
  8.     public void request() {  
  9.           
  10.         this.preRequest();  //在调用真实角色操作之前所附加的操作  
  11.           
  12.         if (realSubject == null) {  
  13.             realSubject = new RealSubject();  
  14.         }  
  15.           
  16.         realSubject.request();  //真实角色所完成的事情  
  17.           
  18.         this.postRequest();  //在真实角色操作之后所附加的操作  
  19.     }  
  20.       
  21.     //自定义的方法,在真实方法执行之前调用的方法  
  22.     private void preRequest() {  
  23.         System.out.println("pre request");  
  24.     }  
  25.       
  26.     //自定义的方法,在真实方法执行之后调用的方法  
  27.     private void postRequest() {  
  28.         System.out.println("post request");  
  29.     }  
  30. }  

在实现代理角色对象时,最重要的一点是要有一个真实对象的引用。

通过这个引用在代理对象中去调用真实对象的方法,并且可以自定义一些其他的操作,比如本例子中的preRequest()和postRequest(),他们分别在之前和之后被调用。

这样做可以记录一下运行时间或打log之类的操作,但这里仅仅是打印了一句话。


4.最后看看main方法中如何调用:

[java] view plain copy print?技术分享技术分享
  1. public class TestProxy {  
  2.   
  3.     public static void main(String[] args) {  
  4.         //实例化一个代理角色对象  
  5.         Subject subject = new ProxySubject();  
  6.         //用代理对象去调用定义的通用方法  
  7.         subject.request();  
  8.     }  
  9. }  

输出为:

pre request

this is real subject

post request

大家看代码后可以发现,这里并没有用到反射的知识。而且对于上面的例子来说,真实角色对象是事先必须已经存在的,并且必须是作为代理对象的内部属性。

如果这样的话,有一个真实角色那就必须在代理角色中有一个他的引用,如果在不知道真实角色的情况下又需要怎么办?这就需要"动态代理"来解决了。

下一篇文章就来介绍"动态代理"。


Java反射学习总结三(静态代理)