代碼已經托管到github:https://github.com/boycy815/asea
該庫的設計最初是為了方便配置RSL,后來發現功能逐漸與Spring接近,所以干脆對功能重新規划了一次取名為Asea,在AS3上實現了基本的IOC功能。
以下內容讓您學會如何使用Asea。
一. Hello World
1 package 2 { 3 import com.alibado.asea.*; 4 5 import flash.display.Sprite; 6 7 public class AseaTest extends Sprite 8 { 9 public function AseaTest() 10 { 11 //定義配置xml 12 var xml:XML = new XML(<asea><trace value="string/hello world"/></asea>); 13 14 //獲取根節點處理器 15 var asea:EaDrop = EaConfig.getDrop("asea"); 16 17 //定義上下文對象 18 var context:Object = {}; 19 20 //執行 21 asea.process(xml, [context]); 22 } 23 } 24 25 }
除非您打算擴展它,否則使用Asea的僅需要四步。
配置xml中定義了您要執行的命令,命令的具體語法將在下面介紹。
上下文對象是xml命令執行的數據環境,換句話說,您可以在xml命令中從上下文對象中獲取數據和寫入數據,您可以嘗試把上下文對象另外保存起來,這樣您就可以通過它獲取到處理后的結果了。這里提醒一點,如果您的上下文對象並非動態對象,那么當您嘗試在xml上寫入上下文環境中不存在的屬性時,系統將報錯(ReferenceError),當然一般來說您沒有必要這么做。
根節點處理器就是一個大烤箱,您把執行命令和上下文數據交給它,它幫您處理。根節點處理器從EaConfig中獲取,一般來說獲取名字是“asea”的根節點處理器是不會錯的,除非您非常確切得知道您的根節點是什么標簽。另外方法process的第三個參數是成功后的回調,其定義應該是function(result:* = null):void,result處理后的結果,如果您的根節點是“asea”,那么result肯定是null,該回調存在的意義在於,考慮您的xml可能是異步處理的,比如在xml中加載個數據什么的。。process的第四個參數是出錯后的回調,定義是function(errorCode:int, message:String, target:String, xml:XML):void。
對了,您可能還注意到process的第二個參數並非直接是context對象,而是一個只有context一個元素的數組。這個問題涉及到作用域鏈,作用域鏈的作用將在后面講到。我知道這樣看起來不太友好,希望哪個好人能幫它再封裝一層吧。
二. 標簽處理器
Asea目前提供的標簽有:asea,class,get,if,lib,method,new,selector,trace,with,bean。
您可以在EaConfig這個類的drops屬性中找到這些定義,drops是個包含所有標簽處理器的數組,如果您定義了自己的標簽處理器,可以push到這個數組中即可生效。
所有的標簽處理器都繼承EaDrop這個類,您只需覆蓋onProcess方法和get name方法即可定義自己的標簽處理器。另外提醒一點,標簽處理器是無狀態的,全局唯一實例,所以如果您的變量不是定義在方法體內,就要小心處理了。
這里貼出了最簡單的標簽處理器
1 package com.alibado.asea.drops 2 { 3 import com.alibado.asea.EaDrop; 4 5 public class EaGet extends EaDrop 6 { 7 8 override public function get name():String 9 { 10 return "get"; 11 } 12 13 14 /** 15 * example: 16 * <get id="myPen" value="pen" > 17 */ 18 override protected function onProcess(dom:XML, value:*, contexts:Array, onComplete:Function, onError:Function = null):void 19 { 20 onComplete(value); 21 } 22 } 23 24 }
在EaGet中覆蓋了public function get name():String,需要在該方法中返回該標簽處理器的要處理的標簽名。
另外還要覆蓋protected function onProcess(dom:XML, value:*, contexts:Array, onComplete:Function, onError:Function = null):void,該方法的第一個參數是處理的xml,系統會保證該xml的根節點名就是get name中指定的名字;第二個參數value是在標簽中的value屬性在上下文環境中查詢到的數據,如果您不想知道查詢的結果想自己處理value屬性,那么您就去訪問xml.@value吧;contexts是上下文環境;onComplete是處理成功后的回調,如果您的標簽處理器會產生結果,那么就往onComplete里面傳遞結果吧,如果您的處理不產生結果,那也要調用一次onComplete,因為整個處理鏈是依賴onComplete進行的,如果您的標簽有id屬性且您傳遞了結果,那么系統會自動把您的結果保存在id屬性指定的地方,onError是處理出錯后的回調,定義已經在上文中提到過了。除非是特別嚴重的錯誤,否則我們不建議因為出錯而不調用onComplete。因為如果您不調用onComplete,系統會認為您的標簽尚未處理完成,整個處理過程將無法繼續。
三. 上下文環境的操作
上下文環境是個數組,其中下標為0的對象為“當前上下文”,數組末尾的對象為“根上下文”,一般來說“根上下文”是我們人為提供的,就像Hello World程序里定義的那個上下文對象。其他上下文對象則是在運行xml時產生的,至於為什么產生,什么時候會產生,這些問題在下文中介紹具體介紹標簽時講解。
有了上下文環境,我們就需要在上下文環境總讀取和寫入數據,通過標簽的value屬性可從上下文環境中讀取數據。
讀取的量可分常量與變量,常量分為string,number,boolean三種類型,例如"string/hello world"是字符串常量,"number/110"是數字常量,"boolean/true"是布爾型常量,其余寫法都算作變量。
@root是一個關鍵字,代表根上下文,我們可以以@root.attr的方式訪問根上下文的屬性,也可以@root.attr.attr2的方式進一步訪問。@this也是一個關鍵字,代表當前上下文環境。如果不使用關鍵字,比如myBall.x這樣的方式,則系統首先搜索當前上下文環境是否有myBall屬性,若是沒有,則再向上一級搜索,直到搜索到根上下文環境,這一點類似與JS的屬性訪問規則。
通過id屬性可保存標簽執行的結果,若是id為myBall.x,那么首先系統將在上下文環境中由內向外搜索myBall屬性,找到myBall對象后往其內設置x屬性。若是myBall屬性不存在,則將會在其當前上下文對象中建立myBall屬性,並且設置x屬性。同樣的myBall.positon.x的話,若是myBall不存在,則建立之,而后建立positon,最后設置x。id的設置同樣支持@root和@this,若是id直接等於@this或者@root,那么你就能直接把上下文對象給覆蓋了。。這相當危險但是有用。
四. 標簽詳解
asea:所有標簽中最重要的一個,該標簽什么屬性也不支持,但是它卻是其他標簽正常運行的容器,它一般作為根節點或者被其他標簽處理器作為父類;
bean:
/** * example: * <bean id="myBean"> * <new id="newObj" value="Pic"> * <get value="box" /> * <get value="number/400" /> * <get value="number/300" /> * <get value="string/this is my title" /> * </new> * <get id="newObj.a" value="box" /> * <get id="newObj.b" value="number/400" /> * <get id="newObj.c" value="number/300" /> * <get id="newObj.d" value="string/this is my title" /> * </bean> */
定義一個對象的定義(並不直接執行內部代碼),內部第一個標簽必須是new標簽,new標簽執行前當前上下文對象是個空對象,new標簽之后當前上下文對象變成new出來的對象。而后的代碼可對new出來的對象設置屬性等操作。。。bean標簽的執行結果是一個對象定義,當每次被訪問時,都會執行一次對應的bean標簽內部的代碼並得到構造出來的內容。
class:
/** * example: <class id="MyClass" value="com.alibado.lib.DemoClass" /> */
定義一個類的別名,value屬性是類的完整命名,id是類的別名。實際上該別名就是上下文環境中的一個Class對象。
get:
/** * example: * <get id="myPen" value="pen" > */
獲取屬性或者轉存屬性,get標簽的執行結果就是value屬性中指定的屬性。
if:
/** * example: * <if value="id"> * <lib value="http://www.alibado.com/lib/myLib.swf" /> * <class id="MyClass" value="com.alibado.lib.DemoClass" /> * </if> * */
邏輯判斷功能的標簽,若是value內的值是布爾型true,則執行內部內容,否則不執行任何操作。
lib:
/** * example: <lib value="http://www.alibado.com/lib/myLib.swf" /> */
該標簽是動態加載swf庫到當前applicationDomain。
method:
/** * example: * <method id="pic" value="draw"> * <get value="number/400" /> * <get value="number/300" /> * <get value="string/this is my title" /> * </method> */
該標簽是執行一個方法,其value值對應的對象必須是個Function,否則結果你懂的。。標簽的輸出是函數執行結果。標簽的子標簽是參數。實際上參數可以是任何標簽,只要能產生輸出均可,內部標簽的當前上下文對象是個數組,該數組將最終成為Function執行的參數。
new:
/** * example: * <new id="myPic" value="Pic"> * <get value="box" /> * <get value="number/400" /> * <get value="number/300" /> * <get value="string/this is my title" /> * </new> */
該標簽的功能是實例化一個對象,value的值可以是上下文中的Class對象,也可以是類的全名(先搜索上下文內容)。new標簽輸出結果是實例化的結果。new標簽內部的標簽是構造函數參數,其實現原理與method標簽一樣,另外,構造函數參數個數不能超過十個。。。
selector:
/** * example: * <selector> * <if value="id1"> * <lib value="http://www.alibado.com/lib/myLib.swf" /> * <class id="MyClass" value="com.alibado.lib.DemoClass" /> * </if> * <if value="id2"> * <lib value="http://www.alibado.com/lib/myLib.swf" /> * <class id="MyClass" value="com.alibado.lib.DemoClass" /> * </if> * </selector> * * 子節點規則:onComplete參數第一個為true則跳出,否則繼續。 */
該標簽類似於switch,當其內部標簽的執行結果是true的時候,才停止執行,否則將一直執行下去。
trace:
/** * example: <trace value="string/hello world" /> */
該標簽直接在控制台輸出value的內容,用於調試。
with:
/** * example: * <with value="ball"> * <get id="aa" value="number/400" /> * <get id="bb" value="number/300" /> * <get id="cc" value="string/this is my title" /> * </with> */
該標簽為其內部的標簽創造一個當前上下文對象,內部標簽的當前上下文對象變成由value指定的對象。
include:
/** * example: * <include value="pen.xml" > */
該標簽可導入一個外部的xml或者上下文中存在的一個xml對象,系統首先搜索value中給定的值是否在上下文中有對應的xml對象,若是有則處理之,若是沒有則搜索是否存在對應的String對象,若是有則將其視為外部xml的URL並加載之,若是沒有則將value內容視為外部XML的URL並加載之。載入的XML與外部享有相同的上下文環境。