1. 程式人生 > >Java動態代理模式理解和實現

Java動態代理模式理解和實現

   在研究了靜態代理模式之後,參照網上的許多部落格,便了解到了關於許多靜態代理的不足之處,當業務邏輯趨於複雜時,需要進行代理的內容增加,就會導致程式碼量急劇增加(當然了,現在沒有遇到過這個情況,也就先跟著道聽途說吧)。於是,為了將編寫程式碼的效率提高,可讀性提高,於是引入了AOP(面向切面程式設計)的概念到實際的應用中,所以動態代理模式也就應運而生。

   首先,我需要解釋一下什麼是AOP(面向切面程式設計),根據網上的解釋,加之我自己對於這一概念的理解,大概就是吃餃子。每個餃子就對應著我們的業務邏輯程式碼,每個餃子的風味不一樣,蘸料也就不一樣,有的人要吃辣,那麼蘸料裡就會加辣椒,有的人不吃辣,則相反。為了遷就每個吃餃子的人,我們是不是就不能直接在餃子里加蘸料,因為這樣不僅影響了餃子的美觀,同時,又不能滿足每個人的口味。所以,將煮好的餃子和不同的蘸料分開盛放,每個人按需進行調味,這樣是最好的。(也就是說,在業務邏輯層寫好之後,如果需要新增一些附屬的驗證功能或者日誌記錄功能,不應該在業務邏輯層完成,而是應該將其獨立出來,通過AOP的方式,來將其進行組合,這樣不僅降低了程式的耦合程度同時也滿足了需求)

   動態代理,就是使用這種AOP思想來進行設計的。現在,接著靜態代理模式的故事繼續向下講。話說,A公司的產品在海外由於B公司的大力推廣而供不應求,B公司也因為這一次優秀的營銷計劃得到了公眾的肯定,也在這次的合作中大賺一筆。於是,為了讓公司能夠擴大經營範圍,所以,B公司設計了一套更為高效和全能的營銷計劃,通過這一計劃,B公司不僅能夠幫助A公司繼續完成銷售任務,同時,也能夠為其他公司提供相應的代理服務。這樣,B公司就能得到更多的利潤。

   B公司新的計劃是:B公司不再與A公司有相同的目標,而是讓A公司排出銷售代表,駐紮在B公司中,銷售代表能夠代表A公司,同時也貫徹落實了A公司的目標和任務(Goal_D)。而現在B公司的目標變為為更多的公司進行代理銷售服務(InvocationHandler),而不變的是B公司依然用自己良好的營銷策略為A公司進行服務,這樣,貨物生產方面的一切都由A公司的銷售代表完成,B公司將不再過問。B公司就擁有了更多人手,進行其他公司事務處理,同時,雙方協調完成任務的效率也有所提高。

   在完成新計劃的實施後,客戶C又看中了A公司的產品,則在與B公司取得聯絡後,B公司確認了客戶C需要的產品來自於A公司,於是通知了駐紮在B公司中的A公司銷售代表,銷售代表將所需要向客戶C呈現的資料都交給B公司,B公司將資料進行了整合並和客戶C商討後完成了交易。

下面通過程式碼來實現整個故事
A公司的目標 Goal_D

package proxy;
public interface Goal_D {
    //A公司的目標,完成自己的工作
         void work();
}

A公司需要完成的工作,確定自己的目標

package proxy;
public class Company_A implements Goal_D{
    public Company_A() {

    }

    @Override
    public void work(){
         System.out.println("生產熱銷產品,並交付給客戶"
); } }

B公司需要完成的工作,確定自己的新目標

package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Company_B implements InvocationHandler{
    private Company_A company_A = null;

    public Object bind(Company_A company_A) {
         this
.company_A = company_A; return Proxy.newProxyInstance(company_A.getClass().getClassLoader(), company_A.getClass().getInterfaces(), this); } private void advertising(){ System.out.println("B公司為產品進行推廣工作"); } private void getOrder(){ System.out.println("B公司獲得訂單,收費,完成交易"); } @Override public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable { advertising(); getOrder(); //完成訂單後,銷售代表通知A公司生產產品交給客戶 arg1.invoke(company_A, arg2); return null; } }

客戶C與B公司進行談判,完成交易

package proxy;
public class Client_C {
    public static void main(String[] args) {
         //通過B公司宣傳瞭解到了A公司產品後,向B公司協商購買事宜
         Company_B company_B = new Company_B();
         //B公司瞭解了客戶需要的是A公司的產品,於是聯絡了A公司的銷售代表
         Goal_D goal = (Goal_D) company_B.bind(new Company_A());
         //完成整個宣傳談判交易流程
         goal.work();
    }
}

執行結果為
B公司為產品進行推廣工作
B公司獲得訂單,收費,完成交易
生產熱銷產品,並交付給客戶

這就是整個動態代理模式的執行程式碼。

   需要注意的是,為何介面Goal_D中的抽象方法work(),可以直接呼叫,並且完成整個程式的執行,其原因在於動態代理時,程式碼會將Goal_D變為最終的代理物件(Proxy),而Proxy物件在呼叫時,實際上是通過InvocationHandler.invoke()來完成呼叫的,這樣以來就解釋了為什麼Goal_D.work()執行時,會讓整個邏輯都完成。

   如果我的理解和正確的方式有出入或者文章中有筆誤,請見諒或者聯絡我。