標籤: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與裝飾模式