java动态代理学习笔记

没事的时候翻看lang.reflect包下的代码,发现有两部份内容:涉及反射和动态代理。 
不少地方均可以看到动态代理的影子,只是一直没仔细看下。 

在学习以前,先提出几个问题,带着问题来看代码: 

1.什么是动态代理? 
2.为何使用动态代理? 
3.使用它有哪些好处? 
4.哪些地方须要动态代理?
 

--------------------分隔线----------------------------- 

和动态代理有关的有两个类 
1.interface InvocationHandler 
Object invoke(Object proxy, Method method, Object[] args) 
只这一个方法,后面再说 

2.class Proxy 
真正表示动态代理的类,提供两个静态方法: 

Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface) 
用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”, 
用来冒充真实的对象。 

Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类), 
它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法, 
invoke方法就是咱们用来作N多事情的地方 -_-。 

--------------------分隔线----------------------------- 

看完上面的代码,大体明白动态代理的含义: 
A接口有c方法,类B实现A接口,本来应该是执行B类中的c方法,可如今不这样作; 
我声明产生B类的代理类B',由它来冒充B类的“兄弟”并“实现”A接口, 
对外界来讲B'应该也有c方法,可当真正调用它的时候, 
它会去执行与它关联InvocationHandler的invoke()方法, 
在这个方法里面你能够作不少事情。这样,这个请求就被“代理”到其它地方去了。 

下面是根据个人理解画的一个说明图 
 


--------------------分隔线----------------------------- 

引用网上的一个例子来讲明问题(有部分改动,转载自:http://callan.iteye.com/blog/161806) 
真实的接口: java

public interface Hello {  
  
    void sayHello(String to);  
    
    void print(String p);   
   
}

它的真实实现类:数组

public class HelloImpl implements Hello {  
      
    public void sayHello(String to) {  
        System.out.println("Say hello to " + to);  
    }  
      
    public void print(String s) {  
        System.out.println("print : " + s);  
    }  
      
}

在这里生成与代理类相关联的InvocationHandler对象 学习

public class LogHandler implements InvocationHandler {  
      
    private Object dele;  
      
    public LogHandler(Object obj) {  
        this.dele = obj;  
    }  
      
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        doBefore();  
        //在这里彻底能够把下面这句注释掉,而作一些其它的事情  
        Object result = method.invoke(dele, args);  
        after();  
        return result;  
    }  
      
    private void doBefore() {  
        System.out.println("before....");  
    }  
      
    private void after() {  
        System.out.println("after....");  
    }  
}

最后是测试类:测试

public class ProxyTest {  
  
    public static void main(String[] args) {  
        HelloImpl impl = new HelloImpl();  
        LogHandler handler = new LogHandler(impl);  
        //这里把handler与impl新生成的代理类相关联  
        Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);  
          
        //这里不管访问哪一个方法,都是会把请求转发到handler.invoke  
        hello.print("All the test");  
        hello.sayHello("Denny");  
    }  
  
}

这里是输出结果: this

  1. before....  spa

  2. print : All the test  代理

  3. after....  日志

  4. before....  code

  5. Say hello to Denny  对象

  6. after....  

--------------------分隔线----------------------------- 

最后试着来回答以前提出的问题: 
1.什么是动态代理? 
一种用于转发请求,进行特殊处理的机制,“动态”应该指的是“运行期”。 
2.为何使用动态代理? 
能够对请求进行任何处理(如事务,日志等,这都是网上说的,我固然能够作任何处理) 
3.使用它有哪些好处? 
如上 
4.哪些地方须要动态代理? 
不容许直接访问某些类;对访问要作特殊处理等,我只能想到这些。
 

--------------------分隔线----------------------------- 

其它一些想法: 

1.若是想声明产生B类的代理类,那个B类必需要实现接口,若是没有接口, 
代理类就不能假装成B类的“兄弟”,也就没有存在的意思, 
其实也能够假装成B类的“孩子”,对外他们有共同的接口,能够这样作吧? 

2.当请求代理类的方法时,这个请求会被转到执行与代理类关联InvocationHandler 
的invoke方法。那InvocationHandler究竟是什么?对它的理解能够是这样: 
它用来处理方法的调用,实现类也有一样的意义;与代理类对象相关联则表示, 
它就是负责处理代理类应该有的动做,把全部的方法请求分发到invoke这个方法上。 



--------------------分隔线----------------------------- 
学习后总结,既能够全面地观察分析,又能加深印象。 
若是个人理解有误,别人的指证会对我产生积极影响。 
若是个人理解正确,帮助其它人理解是个人荣幸。 
初学者,请多多指教。

相关文章
相关标签/搜索