前面一個文章里的代碼很簡單(只是讓大家了解什么是代理),實現的是靜態代理,做為電腦代理商的ComputerProxy,在電腦行業 為電腦生產商(三星,聯想)和客戶提供服務,提供各種方便。
        郁悶的是,如果我現在增加一個行業,比如下面要講到的Cat汽車行業,那么,我們只能增加一個代理了,也就是說我們要再寫一個CatProxy代碼,我們現在假設我們有很多個行業,那么,無疑我們的工作量開始大了,有沒有什么辦法讓我們的代理商實現跨行業代理呢?
        答案是:可以。這就是我們這里講的動態代理產生存在的意義了。

請看代碼

在原有代碼的基礎上我們做了這些寬展:

/*
*汽車批發商
*這樣我們的代碼中就有了電腦和汽車這兩個批發商
*/

public interface Cat {
    
public void buyCat(String name);
}

/*
*勞斯萊斯汽車公司
*/

public class RollsRoyce implements Cat {

    
public void buyCat(String name) {
        
        System.out.println(name
+"  勞斯萊斯公司產品!");
    }


}

/*
*所有行業代理商
*有了它我們的客戶可以通過他買個各種產品
*/

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AllthingsProxy implements InvocationHandler {

    
private Logger logger=
        Logger.getLogger(
this.getClass().getName());
    
    
private Object allthings;
    
    
//實現對象綁定
    public Object bind(Object allthings){
        
        
this.allthings = allthings;
        
        
//這里傳入newProxyInstance的參數分別是 目標object
        
//(Lianxiang,Sanxing),interface(Computer),AllthingsProxy
        return Proxy.newProxyInstance(allthings.getClass().getClassLoader(),
                                    allthings.getClass().getInterfaces(), 
this);
    }

    
    
public Object invoke(Object proxy, Method method, Object[] args)
            
throws Throwable {
        
        Object result 
= null;
        
        
try{
        log(
"method starts " + method);
        
        result
=method.invoke(allthings, args);

        logger.log(Level.INFO , 
"method ends " + method);
        
        }
catch(Exception e){
            log(e.toString());
        }

        
        
return result;
    }

    
    
private void log(String msg){
        logger.log(Level.INFO,msg);
    }


}


在測試類BuyAllThings中,我們通過bing方法綁定對象(所要買的東西),讓代理商了解到,客戶想買什么?
(這里重在了解模式,具體方法的實現如不了解請自行查詢API文檔)


/*
*三個客戶兩個買電腦一個買汽車
*他們找到同個代理商
*/

public class BuyAllThing {

    
public static void main(String[] args) {
        
        AllthingsProxy allthingsproxy 
= new AllthingsProxy();
        
        Computer SanxingProxy
=(Computer)allthingsproxy.bind(new Sanxing());
        
        SanxingProxy.buyComputer(
"我想買一臺三星電腦");
        
        Computer lianxiangProxy
=(Computer)allthingsproxy.bind(new Lianxiang());
        
        lianxiangProxy.buyComputer(
"我想買一臺聯想電腦");
        
        Cat RollsRoyceProxy
=(Cat)allthingsproxy.bind(new RollsRoyce());
        
        RollsRoyceProxy.buyCat(
"我想買一輛勞斯萊斯汽車");

    }


}

執行結果

我想買一臺三星電腦  三星電腦公司產品!
我想買一臺聯想電腦  聯想電腦公司產品!
我想買一輛勞斯萊斯汽車  勞斯萊斯公司產品!
2007-8-9 13:08:41 com.lusm.spring.AllthingsProxy log
信息: method starts 
public abstract void com.lusm.spring.Computer.buyComputer(java.lang.String)
2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy invoke
信息: method ends 
public abstract void com.lusm.spring.Computer.buyComputer(java.lang.String)
2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy log
信息: method starts 
public abstract void com.lusm.spring.Computer.buyComputer(java.lang.String)
2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy invoke
信息: method ends 
public abstract void com.lusm.spring.Computer.buyComputer(java.lang.String)
2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy log
信息: method starts 
public abstract void com.lusm.spring.Cat.buyCat(java.lang.String)
2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy invoke
信息: method ends 
public abstract void com.lusm.spring.Cat.buyCat(java.lang.String)

我們可以任意的增加代理商的業務,比如,叫他代理電器,食物......,我們看到我們不需要更改原有的代碼。這是動態代理帶來的好處!

那我們的AllthingsProxy是怎么作到動態代理的呢?

AllthingsProxy寬展了InvocationHandler并實現了里面的代理方法,返回一個Object對象,

    public Object invoke(Object proxy, Method method, Object[] args)
    
throws Throwable;

來實現對汽車,電腦這些批發商的動態代理(代理商同過它 代理所有行業)。

AllthingsProxy中的bind實現了客戶和代理商間的通信(通過它代理商知道客戶想要買什么)

這和我們 BuyAllThing 測試類main中

代理對象=(綁定對象)allthingsproxy.bind(綁定對象(客戶想買的東西))

想對應。

         呵呵 ,講完了!也許有的朋友看不懂這里在說什么? 不必著急,學習都需要過程,等你的學習到某個階段的時候,回頭想想,也許認識就會加深許多,本人覺得Java是比較高級的語言,自身的發展也只直遵循著軟件設計優化(代碼重用)方向發展,重視設計思想,而不是去改變語言的語法或接口api,這是許多語言所缺乏的,如一個在VC6中編寫的代碼,拿到Visual Studio2005,Visual Studio2008去運行很容易出現問題。

       也許你并不清楚我在說什么?但是這一切會在你的Spring學習中漸漸清楚起來!

       以后的代碼可能需要必要的IDE才能使用,本人使用的是:
       MyEclipse6.0M1+Eclipse3.3 
       數據庫用的是:
      Oralce10g或者Mysql6.0

      祝你好運氣?。?!