代理,动态代理,反射

阅读更多

Java中Proxy,Dynamic Proxy以及Reflection是什么关系呢?谈这个问题之前,我们要先了解三者究竟是什么东西。
    一、Proxy。面向对象中Proxy是比较常用的,作为GOF 23个模式之一,Proxy在Design Patterns一书中有着详细的描述。Proxy的使用范围很广,下面以一个简单的访问控制为例。在这种情况下,外部使用者要想使用某个对象,必须通过该对象的代理进行。在这里,Proxy充当着“网关”的角色,这样,在外部触及到内部对象之前,我们可以做很多有意义的工作,如身份认证等。下面是一个简单的例子:

java 代码
  1. public class ProxyTest { //劳工使用方   
  2.   public static void main(String[] args) {    
  3.       Job job = new Proxy(new Worker()); //劳工使用方找到代理,让它进行code的工作   
  4.       job.code();   
  5.   }   
  6. }   
  7. interface Job{   
  8.    public void code();   
  9. }   
  10. class Proxy implements Job{ //代理声称可以code   
  11.  private Worker wrk;   
  12.  public Proxy(Worker wrk){   
  13.   this.wrk = wrk;   
  14.  }   
  15.  public void code(){   
  16.    //代理把工作交给worker之前,可以进行使用者是否合法   
  17.   System.out.println("Check the permission");   
  18.   wrk.code();   
  19.  //worker做完以后,代理还可以做更多的工作   
  20.   System.out.println("Get the saraly");   
  21.  }   
  22. }   
  23. //Worker实际做code的工作,但是使用者不能直接找到他,   
  24. //而要通过代理   
  25. class Worker implements Job{   
  26.  public void code() {   
  27.     System.out.println("Worker code actually");   
  28.  }   
  29.     
  30. }   


   二、Dynamic Proxy。上面的Proxy,也可以叫做静态代理,它的特征是代理和实际作业的对象的类都是在编译期间就已经定下来的。与此相对的是动态代理,其代理是在程序运行期间动态产生的。Java对动态代理提供了相应的API,但只能接口方法的动态代理。动态代理一个典型应用就是实现数据库的连接池。由于使用JDBC的程序员习惯在使用完数据库的Connection对象后调用该对象的close方法关闭连接,这样连接池就失去作用了。这个问题我们可以使用动态代理技术来解决,当程序员调用Connection的close方法时,我们将其拦截下来,将其归还到连接池中,而不是直接关闭物理连接。下面是动态代理的一个实例。

java 代码
  1. public class DynamicProxy {   
  2.    public static void main(String[] args) throws Exception {   
  3.       Job job = JobFactory.getJob();   
  4.       job.code();   
  5.    }   
  6. }   
  7. interface Job{   
  8.   public void code();    
  9. }   
  10.   
  11. class Worker implements Job{   
  12.   public void code() {   
  13.     System.out.println("worker code");   
  14.   }   
  15.     
  16.   public void play(){   
  17.     System.out.println("worker play");   
  18.    }   
  19. }   
  20. class Handler implements InvocationHandler{   
  21.     private Worker worker;   
  22.     public Handler(Worker worker){   
  23.           this.worker = worker;   
  24.      }   
  25.    public Object invoke(Object obj, Method mtd, Object[] objs) throws Throwable {   
  26.      Object res = null;   
  27.      System.out.println("check permission");   
  28.      res = mtd.invoke(worker, objs);   
  29.      System.out.println("get the saraly");   
  30.      return res;   
  31.    }    
  32. }   
  33. class JobFactory {   
  34.  public static Job getJob() {   
  35.   Worker worker = new Worker(); //这是代理,可以代理接口指定的工作   
  36.   if (!(worker instanceof Job ))//判断是否有资格当这些工作的代理   
  37.    return null;   
  38.   /* construct a invocation handler with the impl instance */  
  39.   InvocationHandler handler = new Handler(worker); //这是实际工作的人   
  40.  /* get the class info, and the class loader used by this factory */  
  41.   Class[] interfaces = new Class[] { Job.class};   
  42.   ClassLoader loader = JobFactory.class.getClassLoader();   
  43.    Job proxy = (Job) Proxy.newProxyInstance(loader, interfaces, handler);   
  44.     return proxy;   
  45.  }   
  46. }   
  47.   
   动态代理与普通的代理相比较,最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理(invoke),这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。在JDBC连接池的例子中,如果我们使用普通的代理模式进行,那么我们要对Connection中的每一个方法进行单独处理,那么是比较繁琐的。如果,我们用动态代理的方式,实现起来就比较优雅。
    三、Reflection。Java中通过反射技术,我们可以在运行过程中得到相应类的各种方法和属性,并且可以进行修改和调用。动态代理技术就是基于反射实现的。当然,反射技术用处还很多,譬如JavaBean技术。
     现在是比较清楚了,Proxy和Dynamic Proxy都是一种模式,两者实现的功能相当,但是方式不同;Reflection是实现后者的技术基础。

你可能感兴趣的:(工作,JDBC)