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這個方法上。 



--------------------分隔線----------------------------- 
學習後總結,既能夠全面地觀察分析,又能加深印象。 
若是個人理解有誤,別人的指證會對我產生積極影響。 
若是個人理解正確,幫助其它人理解是個人榮幸。 
初學者,請多多指教。

相關文章
相關標籤/搜索