前言
关于自定义元数据标签,网上已经有不少资料了。不过大部分都是讲怎么在代码里使用,但是关于怎么编译到swf里面去,在实际编译后怎么运行却很少提及。所以我在这里会稍微提及一下元数据标签,后面会讲怎么把自己的标签给编译到swf中,使得在实际项目中可以使用(注意,debug方式是可以保留元标签数据的,不做特别设置,发布版是不会保留的)
一 概念
在讲元数据标签之前,先讲一个概念,那就是反射,我们自定义元标签,很多时候就是为了反射服务。
1. 先引用一下反射的概念
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ 、OpenC++ 、MetaXa和OpenJava等就是基于反射机制的语言
2. 自定义元数据的作用
我个人理解,在AS3中,它可以在程序运行中动态地检测类的相关信息,利用这些信息做相关的操作。比如数据检测和类型判断、以及动态反射类实例、类方法,类型填充等等。
在编写框架和做底层代码的时候特别有用,比较方便写出通用的代码。
二 元数据标签的实例
1. AS3自带的元数据标签
FlashBuilder工程最常用的
//指定SWF在启动时的属性
[SWF(width="1330", height="845", frameRate="30", backgroundColor="#ffffff")]
//将外部资源(图像)编译到SWF中。
[Embed(source="assets/fight/background.jpg")]
/**队列全部加载后触发*/
[Event(name="moreComplete",type="com.asframe.net.NetEvent")]
使用FlashBuilder自带的元数据标签有个好处就是,可以在编码阶段,这个标签就实现效果了。
- 比如事件的提示,数据类型的绑定(Bindable)
- 还有一种就是在编译的时候产生作用,比如SWF是设置swf的相关参数,Embed把外部资源嵌入到swf中
2. 自定义元数据标签
我们自定义元数据标签比较最大的用处的就是在运行时发挥作用了。自定义标签的名字可以任意取的,用自己的名字都可以,比如
[Soda(sex="男",age="18")]
我们可以把这个放到class上面
[Soda(sex="男",age="18")]
public class MyMetadataTest extends Sprite
也可以放在属性和方法中
[Prop(key="array",value="1,3,65,6")]
public var ary:Array;
[Call(sex="男",age="18")]
public function mateData(sex:String,age:int):void
看一下完整的类
[Soda(sex="男",age="18")]
public class MyMetadataTest extends Sprite
{
[Prop(key="array",value="1,3,65,6")]
public var ary:Array;
public function MyMetadataTest()
{
//生成描述对象的xml文件
var xml:XML = describeType(this);
trace(xml);
}
[Call(sex="男",age="18")]
public function mateData(sex:String,age:int):void
{
trace("sex:" + sex,"age:" + age);
}
}
3. 输出元数据标签
程序运行中,我们主要通过describeType来得到类的相关标签信息
describeType生成描述 ActionScript 对象(命名为方法的参数)的 XML 对象。此方法实现 ActionScript 语言的反射编程概念
直接得到一个xml文件
var xml:XML = describeType(this);
trace(xml);
那么我们重点关注是我们刚刚自定义的元数据标签
[Prop(key="array",value="1,3,65,6")]
public var ary:Array;
//关于属性的
<variable name="ary" type="Array">
<metadata name="Prop">
<arg key="key" value="array"/>
<arg key="value" value="1,3,65,6"/>
</metadata>
</variable>
variable 是变量的元素,所有的public变量都会有这个对应的描述
[Call(sex="男",age="18")]
public function mateData(sex:String,age:int):void
//关于方法的
<method name="mateData" declaredBy="MyMetadataTest" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="int" optional="false"/>
<metadata name="Call">
<arg key="sex" value="男"/>
<arg key="age" value="18"/>
</metadata>
</method>
method 是描述方法的元素,所有的public方法都会有这个对应的描述
在这里我们不详细介绍关于describeType内容,那么通过解析XML就可以得到我们需要的信息,例如那个方法,我们都是可以把元数据标签的数据传递到方法里去输出来。
4. 关于后续运用(反射)
因为这里不是将怎么详细运用元数据标签,所以就不做深入的介绍了。实际上我们还得把这个xml描述文件给解析出来并且进行归类,比如分好属性、方法,以及标签对象等。然后封装成一系列的API,这样才能方便的进行相关的反射操作。
后续我会单独写一些文章来深入这些用法。比如:
- 直接把XML、Json文件转换成Bean的数据结构对象
- 怎么做到依赖注入,自动填充属性
- 在Class new出来资源就加载好他配置的资源(Res(“assets/img.png”))
三 自定义元数据标签编译到SWF
- 首先我们要来了解Flash命令行编译mxmlc这个指令的相关参数,其他的我们不这里不讲,主要是看他的其中一个参数。
-compiler.keep-as3-metadata [name] [...]
别名 -keep-as3-metadata
在 SWF 中保留指定的元数据 (高级, 可重复)
- 事实上下面你介绍的几种方式,最终原理其实还是利用mxmlc这个指令,然后传递相关的参数进去。知道这点,那么我们就好根据不同的编译环境工具来传递相关的参数了。
1. FlashBuilder的设置
打开FlashBuilder工程的属性,在ActionScrpit编译器那里 的附加的编译参数框里输入
-locale en_US -keep-as3-metadata+=Config,Bean,Ref,Res
如图:
2. 通过Ant的build.xml文件编译设置
注意,下面的xml代码是我截取实际项目的部分设置,需要详细了解Ant编译Flash项目的同学,可以另外查相关的资料。
<target name="compile">
<mxmlc file="${src_dir}/target.as" output="target.swf">
<compiler.source-path path-element="${src_dir}"/>
<library-path dir="${libs_dir}" append="true">
<include name="*.swc" />
</library-path>
<compiler.keep-as3-metadata>Config</compiler.keep-as3-metadata>
<compiler.keep-as3-metadata>Res</compiler.keep-as3-metadata>
<compiler.keep-as3-metadata>Ref</compiler.keep-as3-metadata>
<compiler.keep-as3-metadata>Bean</compiler.keep-as3-metadata>
</mxmlc>
</target>
3. flex-config.xml的设置
flex-config.xml涵盖flex编译及其他控制的所有选项,对于命令行编译来说,mxmlc复杂的编译选项对于命令行的输入简直就是噩梦,而使用flex-config.xml可以方便的修改编译选项,并且一次修改就可以在后续的所有mxmlc编译过程中保存下来。
不过它缺陷也很明显,那就是对所有项目都是一样,所以有时我们可以通过ant的builder文件做不同的设置
- 回归正题,看看我们flex-config.xml里如何加入我们自定义标签。
找到keep-as3-metadata,可以看到默认他注释掉了,并且有说明,很清晰。
<!-- Keep the following AS3 metadata in the bytecodes. -->
<!-- Warning: For the data binding feature in the Flex framework to work properly, -->
<!-- the following metadata must be kept: -->
<!-- 1. Bindable -->
<!-- 2. Managed -->
<!-- 3. ChangeEvent -->
<!-- 4. NonCommittingChangeEvent -->
<!-- 5. Transient -->
<!--
<keep-as3-metadata>
<name>Bindable</name>
<name>Managed</name>
<name>ChangeEvent</name>
<name>NonCommittingChangeEvent</name>
<name>Transient</name>
</keep-as3-metadata>
-->
修改成我们自己需要的参数进去
<keep-as3-metadata>
<name>Config</name>
<name>Bean</name>
<name>Res</name>
<name>Ref</name>
</keep-as3-metadata>
参考和相关主题资料的详细介绍