天天看點

Java動态代理

  動态代理技術是整個java技術中最重要的一個技術,它是學習java架構的基礎,不會動态代理技術,那麼在學習Spring這些架構時是學不明白的。

  動态代理技術就是用來産生一個對象的代理對象的。在開發中為什麼需要為一個對象産生代理對象呢?

  舉一個現實生活中的例子:歌星或者明星都有一個自己的經紀人,這個經紀人就是他們的代理人,當我們需要找明星表演時,不能直接找到該明星,隻能是找明星的代理人。比如劉德華在現實生活中非常有名,會唱歌,會跳舞,會拍戲,劉德華在沒有出名之前,我們可以直接找他唱歌,跳舞,拍戲,劉德華出名之後,他幹的第一件事就是找一個經紀人,這個經紀人就是劉德華的代理人(代理),當我們需要找劉德華表演時,不能直接找到劉德華了(劉德華說,你找我代理人商談具體事宜吧!),隻能是找劉德華的代理人,是以劉德華這個代理人存在的價值就是攔截我們對劉德華的直接通路!

  這個現實中的例子和我們在開發中是一樣的,我們在開發中之是以要産生一個對象的代理對象,主要用于攔截對真實業務對象的通路。那麼代理對象應該具有什麼方法呢?代理對象應該具有和目标對象相同的方法

  是以在這裡明确代理對象的兩個概念:

    1、代理對象存在的價值主要用于攔截對真實業務對象的通路。

    2、代理對象應該具有和目标對象(真實業務對象)相同的方法。劉德華(真實業務對象)會唱歌,會跳舞,會拍戲,我們現在不能直接找他唱歌,跳舞,拍戲了,隻能找他的代理人(代理對象)唱歌,跳舞,拍戲,一個人要想成為劉德華的代理人,那麼他必須具有和劉德華一樣的行為(會唱歌,會跳舞,會拍戲),劉德華有什麼方法,他(代理人)就要有什麼方法,我們找劉德華的代理人唱歌,跳舞,拍戲,但是代理人不是真的懂得唱歌,跳舞,拍戲的,真正懂得唱歌,跳舞,拍戲的是劉德華,在現實中的例子就是我們要找劉德華唱歌,跳舞,拍戲,那麼隻能先找他的經紀人,交錢給他的經紀人,然後經紀人再讓劉德華去唱歌,跳舞,拍戲。

  現在要生成某一個對象的代理對象,這個代理對象通常也要編寫一個類來生成,是以首先要編寫用于生成代理對象的類。在java中如何用程式去生成一個對象的代理對象呢,java在JDK1.5之後提供了一個"java.lang.reflect.Proxy"類,通過"Proxy"類提供的一個newProxyInstance方法用來建立一個對象的代理對象,如下所示:

  newProxyInstance方法用來傳回一個代理對象,這個方法總共有3個參數,ClassLoader loader用來指明生成代理對象使用哪個類裝載器,Class<?>[] interfaces用來指明生成哪個對象的代理對象,通過接口指定,InvocationHandler h用來指明産生的這個代理對象要做什麼事情。是以我們隻需要調用newProxyInstance方法就可以得到某一個對象的代理對象了。

  在java中規定,要想産生一個對象的代理對象,那麼這個對象必須要有一個接口,是以我們第一步就是設計這個對象的接口,在接口中定義這個對象所具有的行為(方法)

  1、定義對象的行為接口

2、定義目标業務對象類

3、建立生成代理對象的代理類

測試代碼:

運作結果如下:

  

  Proxy類負責建立代理對象時,如果指定了handler(處理器),那麼不管使用者調用代理對象的什麼方法,該方法都是調用處理器的invoke方法。

  由于invoke方法被調用需要三個參數:代理對象、方法、方法的參數,是以不管代理對象哪個方法調用處理器的invoke方法,都必須把自己所在的對象、自己(調用invoke方法的方法)、方法的參數傳遞進來。

  在動态代理技術裡,由于不管使用者調用代理對象的什麼方法,都是調用開發人員編寫的處理器的invoke方法(這相當于invoke方法攔截到了代理對象的方法調用)。并且,開發人員通過invoke方法的參數,還可以在攔截的同時,知道使用者調用的是什麼方法,是以利用這兩個特性,就可以實作一些特殊需求,例如:攔截使用者的通路請求,以檢查使用者是否有通路權限、動态為某個對象添加額外的功能。