JStorm與Storm源碼分析(五)--SpoutOutputCollector與代理模式

來源:互聯網
上載者:User

標籤:main   ack   task   put   todo   應用   int   stack   設計   

本文主要是解析SpoutOutputCollector源碼,順便分析該類中所涉及的設計模式–代理模式。 
首先介紹一下Spout輸出收集器介面–ISpoutOutputCollector,該介面主要聲明了以下3個抽象方法用來約束ISpoutOutputCollector的實作類別。介面定義與方法說明如下:

/** * ISpoutOutputCollector:Spout輸出收集器介面 */public interface ISpoutOutputCollector {    /**     * 改方法用來向外發送資料,它的傳回值是該訊息所有發送目標的taskID集合;     * 參數:     * streamId:訊息Tuple將要被輸出到的流     * tuple:要輸出的訊息,是一個Object列表     * messageId:輸出訊息的標記資訊,如果messageId被設定為null,則Storm不會追蹤該訊息,     * 否則它會被用來追蹤所發出的訊息處理情況     */    List<Integer> emit(String streamId, List<Object> tuple, Object messageId);    /**     * 該方法與上面emit方法類似,區別在於:     * 1.資料(訊息)只由所指定taskId的Task接收;(這就意味著如果沒有下遊節點接收該訊息,則該訊息就沒有被真正發送)     * 2.該方法要求參數streamId所對應的流必須為直接流,接收端的Task必須以直接分組的方式來接收訊息,     * 否則會拋出異常.     */    void emitDirect(int taskId, String streamId, List<Object> tuple, Object messageId);    /**     * 用來處理異常     */    void reportError(Throwable error);}

Storm提供了介面ISpoutOutputCollector的預設類SpoutOutputCollector,這個類實際上是一個代理類,該類持有一個ISpoutOutputCollector類型的對象,所有的操作實際上都過該對象來實現的。SpoutOutputCollector定義如下:

public class SpoutOutputCollector implements ISpoutOutputCollector {    /**     * 持有SpoutOutputCollector要代理的對象     */    ISpoutOutputCollector _delegate;    public SpoutOutputCollector(ISpoutOutputCollector delegate) {        _delegate = delegate;    }    /**     * 實現了介面中的emit方法,並且提供了它的幾個重載方法     * eg.如果不指定streamId,預設使用default,如果不指定messageId,則預設使用空(null)     */    public List<Integer> emit(String streamId, List<Object> tuple, Object messageId){        return _delegate.emit(streamId, tuple, messageId);    }    public List<Integer> emit(List<Object> tuple, Object messageId) {        return emit(Utils.DEFAULT_STREAM_ID, tuple, messageId);    }    public List<Integer> emit(List<Object> tuple) {        return emit(tuple, null);    }    public List<Integer> emit(String streamId, List<Object> tuple) {        return emit(streamId, tuple, null);    }    /**     * 實現了介面中的emitDirect方法,同時也提供了幾個重載方法,與上面emit方法一致.     */    public void emitDirect(int taskId, String streamId, List<Object> tuple, Object messageId) {        _delegate.emitDirect(taskId, streamId, tuple, messageId);    }    public void emitDirect(int taskId, List<Object> tuple, Object messageId) {        emitDirect(taskId, Utils.DEFAULT_STREAM_ID, tuple, messageId);    }    public void emitDirect(int taskId, String streamId, List<Object> tuple) {        emitDirect(taskId, streamId, tuple, null);    }    public void emitDirect(int taskId, List<Object> tuple) {        emitDirect(taskId, tuple, null);    }    /**     * 處理異常方法的實現     */    @Override    public void reportError(Throwable error) {        _delegate.reportError(error);    }}

PS: 
代理模式主要分為兩種:靜態代理和動態代理

靜態代理: 
在程式運行前代理類與委託類的關係在運行前就確定,即在程式運行前就已經存在代理類的位元組碼檔案了. 
代理模式角色: 
Subject(抽象主題角色):可以是抽象類別也可以是介面,聲明了被委託角色和委託類共有的處理方法; 
RealSubject(具體主題角色):又稱被委託角色、被代理角色,是商務邏輯的具體執行者; 
ProxySubject(代理主題角色):又稱委託類、代理類,負責對真實角色的應用, 
把所有抽象主題類定義的方法限制委託給具體主題角色來實現,並且在具體主題角色處理完畢前後做預先處理和善後處理.

靜態代理模式案例如下:

//抽象主題public interface Subject {    public void process(String taskName);}

被代理角色:

public class RealSubject implements Subject {    @Override    public void process(String taskName) {        System.out.println("正在執行任務:"+taskName);        try {            Thread.sleep(500);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

代理類:

public class ProxySubject implements Subject {    //代理類持有一個委託類的對象引用    private Subject delegate;    public ProxySubject(Subject delegate){        this.delegate=delegate;    }    @Override    public void process(String taskName) {        //預先處理        this.before();        //將請求指派給委託類處理        delegate.process(taskName);        //善後處理        this.after();    }    private void before(){        System.out.println("預先處理!");    }    private void after(){        System.out.println("善後處理!");    }}

案例測試:

public class Test {    public static void main(String[] args) {        RealSubject subject = new RealSubject();        ProxySubject p = new ProxySubject(subject);        p.process("排水");    }}

測試結果:

預先處理!正在執行任務:排水善後處理!

靜態代理類的優缺點: 
優點: 
業務類只需關注商務邏輯本身,這樣就保證了業務類的重用性. 
缺點: 
代理對象的一個介面只服務於一種類型的對象.當要代理的方法很多,就要為每一種方法進行代理。因此靜態代理在程式規模變大時就無法很好地勝任工作了.

動態代理: 
代理類和委託類的關係在程式運行時才確定的.動態代理類的源碼是在程式運行期間由JVM根據反射等機制動態產生,所以不存在代理類的位元組碼檔案.

動態代理模式案例如下:

public interface Service {    //目標方法     public void process();}
public class UserServiceImpl implements Service {    @Override    public void process() {         System.out.println("使用者service處理");      }}

動態代理實現執行個體:

public class MyInvocatioHandler implements InvocationHandler {    private Object target;    public MyInvocatioHandler(Object target) {        this.target = target;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        //System.out.println("-----before-----");        this.before();        Object result = method.invoke(target, args);       // System.out.println("-----end-----");        this.after();        return result;    }    // 組建代理程式對象    public Object getProxy() {        ClassLoader loader = Thread.currentThread().getContextClassLoader();        Class<?>[] interfaces = target.getClass().getInterfaces();        return Proxy.newProxyInstance(loader, interfaces, this);    }    private void before(){        System.out.println("預先處理!");    }    private void after(){        System.out.println("善後處理!");    }}

案列測試:

public class ProxyTest {    public static void main(String[] args) {        Service service = new UserServiceImpl();        MyInvocatioHandler handler = new MyInvocatioHandler(service);        Service serviceProxy = (Service)handler.getProxy();        serviceProxy.process();    }}

測試結果:

預先處理!使用者service處理善後處理!

動態代理的優缺點: 
優點: 
介面中的所有方法都被轉移到調用處理器一個集中的方法中在方法“運行時”動態加入,決定你是什麼類型,較靈活 
缺點: 
1. 與靜態代理相比,效率降低了 
2. JDK動態代理只能對實現了介面的類進行代理

歡迎關注下面二維碼進行技術交流: 

JStorm與Storm源碼分析(五)--SpoutOutputCollector與代理模式

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.