JStorm與Storm源碼分析(七)--BasicBoltExecutor與裝飾模式

來源:互聯網
上載者:User

標籤:nbsp   src   執行   executor   .exe   inpu   out   執行個體化   方式   

在Storm中IBasicBolt的主要作用是為使用者提供一種更為簡單的Bolt編寫方式,更為簡單體現在Storm架構本身幫你處理了所發出訊息的Ack、Fail和Anchor操作,而這部分操作是由執行器BasicBoltExecutor 實現的。 
下面我們看一下BasicBoltExecutor的源碼:

/** * BasicBoltExecutor實現了IRichBolt介面 * 在該類中持有一個IBasicBolt成員變數用於調用轉寄 * 說明: * 該類是基於裝飾模式實現的. */public class BasicBoltExecutor implements IRichBolt {    public static Logger LOG = LoggerFactory.getLogger(BasicBoltExecutor.class);        //持有IBasicBolt類型的變數    private IBasicBolt _bolt;    //定義了成員變數_collector    private transient BasicOutputCollector _collector;    public BasicBoltExecutor(IBasicBolt bolt) {        _bolt = bolt;    }    /**     * 實現declareOutputFields方法,但它實際上是     * _bolt調用declareOutputFields方法     */    public void declareOutputFields(OutputFieldsDeclarer declarer) {        _bolt.declareOutputFields(declarer);    }    /**     * 實現prepare方法,     * 實際上是調用_bolt的prepare方法,     * 並執行個體化BasicOutputCollector     */    public void prepare(Map stormConf, TopologyContext context,             OutputCollector collector) {        _bolt.prepare(stormConf, context);        _collector = new BasicOutputCollector(collector);    }    /**     * 實現execute方法     */    public void execute(Tuple input) {        //設定運行器上下文,        //它表示經execute方法發送出去的訊息都是由輸入訊息產生的,        //即輸出的訊息都將標記為輸入訊息所衍生出來的訊息,        //這是使用IBasicBolt實現訊息追蹤的重要一環        _collector.setContext(input);        try {            //調用_bolt的execute方法            _bolt.execute(input, _collector);            //對輸入的訊息進行Ack操作.            //這一步意味著基於當前輸入訊息的處理和衍生訊息的發送已經完成,            //這時就可以對該訊息進行Ack操作了.            _collector.getOutputter().ack(input);        } catch(FailedException e) {            //Storm捕獲所有的FailedException,並對輸入的訊息進行Fail操作。            //如果捕獲的異常為ReportedFailedException的執行個體,            //則調用reportError回調方法,給使用者一個機會去處理異常            //FailedException是Storm定義的一種基本異常,用來進行訊息的失敗重發等操作,            //並不會導致Topology運行停止            if(e instanceof ReportedFailedException) {                _collector.reportError(e);            }            _collector.getOutputter().fail(input);        }    }    public void cleanup() {        _bolt.cleanup();    }    public Map<String, Object> getComponentConfiguration() {        return _bolt.getComponentConfiguration();    }}

先說說裝飾模式的結構,裝飾模式UML類圖: 

如所示,裝飾模式的角色構成: 
(1)抽象組件角色-Component:給出一個抽象介面,以規範或約束準備接收附加職責的對象. 
(2)具體組件對象-ConcreteComponent:實現了組件對象的介面,通常是被裝飾器裝飾的原始對象. 
(3)裝飾角色-Decorator:所有裝飾器的抽象父類,需要定義一個與組件介面一致的介面, 
並持有一個Component對象,其實就是持有被裝飾的對象 
(4)具體裝飾對象-ConcreteDecorator:實際的裝飾器對象,負責給組件對象添加附加的功能

現在舉一個常見的例子(沖咖啡)來說明一下。 
我敲代碼困了,想沖一杯咖啡來提提神,但我怕咖啡苦,便向咖啡裡加點糖(用糖裝飾一番),喝著喝著覺得沒有牛奶香,邊往咖啡裡到點牛奶(用牛奶裝飾咖啡一番),這整個過程便可看成裝飾模式. 
代碼: 
1.先定義一個介面用來約束職責對象

/** * Component   * 抽象構建角色, * 約束或規範準備接收附加責任的對象 */public interface Component {    public void operation();}

2.實現組件對象的介面,它是被裝飾器裝飾的原始對象(這裡是咖啡)

/** * ConcreteComponent   * 接收附加責任 */public class ConcreteComponent implements Component {    @Override    public void operation() {        System.out.println("的咖啡");    }}

3.定義裝飾器

/** * Decorator裝飾角色  */public abstract class Decorator implements Component {    //持有一個構建對象的執行個體    private Component component;    public Decorator(Component component){        this.component=component;    }    @Override    public void operation() {        component.operation();    }}

4.實現加糖裝飾器和加牛奶裝飾器

/**  * ConcreteDecorator1 * 加糖裝飾器 */public class ConcreteDecorator1 extends Decorator {    public ConcreteDecorator1(Component component) {        super(component);        // TODO Auto-generated constructor stub    }    public void operation(){        System.out.print("加糖");        super.operation();    }}
/** * ConcreteDecorator2    * 加奶裝飾器 */public class ConcreteDecorator2 extends Decorator {    public ConcreteDecorator2(Component component) {        super(component);        // TODO Auto-generated constructor stub    }    public void operation(){        System.out.print("加奶");        super.operation();    }}

5.測試

public class Test {    public static void main(String[] args) {        // TODO Auto-generated method stub        Component component=new ConcreteComponent();        Decorator decorator1=new ConcreteDecorator2(component);        Decorator decorator2=new ConcreteDecorator1(decorator1);        decorator2.operation();    }}

6.測試結果

加糖加奶的咖啡

jdk中也大量使用裝飾模式。比如Java流介面中輸出資料流部分 
OutputStream就相當於裝飾模式中的Component; 
FileOutputStream、ObjectOutputStream這幾個對象直接繼承了OutputStream, 
還有一些對象直接繼承OutputStream對象,比如:ByteArrayOutputStream、PipedOutputStream等.這些對象相當於裝飾模式中的ConcreteComponent,是可以被裝飾器裝飾的對象. 
FilterOutputStream相當於裝飾模式中的Decorator,而他的子類DataOutputStream、BufferedOutputStream就相當於裝飾模式中的ConcreteDecorator。FilterOutputStream和它的子類對象的構造器都是傳入組件OutputStream。對照上述將的裝飾模式的結構圖,由此可見這部分類的設計完全採用裝飾模式. 
同理輸入資料流部分也類似。

註:內容部分為學習李明老師Storm源碼分析的筆記整理。 
歡迎關注下面二維碼進行技術交流:

 

JStorm與Storm源碼分析(七)--BasicBoltExecutor與裝飾模式

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.