在这个例子中,Shapes.swf是主程序,当RSL加载完毕后实例化主类ShapesMain。如果没有导入RSL中的定义,创建ShapesMain实例的时候就会因为在应用程序域中找不到对应的类而发生校验错误。
注意:Flex中的RSL
这里讨论的方法是最底层的方法,不应该用于Flex开发。Flex框架中有自己的一套RSLs处理机制,更多关于RSL在Flex中的应用,请参考Flex Runtime Shared Libraries (Flex 4)。
Getting Definitions Dynamically 动态获取定义我们可以用方法获取不在应用程序域内的定义,或者被父域覆盖的定义。这个方法返回应用程序域及其任意父域内的定义引用。在当前应用程序域内使用getDefinition方法的效果等同于全局函数。
我们也可以通过SWF的来获得在ApplicationDomain.currentDomain以外的应用程序域。在下面的例子中我们用Loader加载了一个SWF文件,然后在加载的那个应用程序域中提取com.example.Box类的定义。
try { var domain:ApplicationDomain = loader.contentLoaderInfo.applicationDomain; var boxClass:Class = domain.getDefinition("com.example.Box") as Class; var boxInstance:Object = new boxClass(); }catch(err:Error){ trace(err.message); }以上的例子中包含了两个知识点。首先,getDefinition方法的返回值被显式的转换为Class类型,这是因为getDefinition默认返回的是Object类型,有可能代表了除了类类型以外的其他类型(函数,命名空间,接口)。其次,这个操作应该要放在try-catch函数体内,因为如果getDefinition查找定义失败将会抛出错误。或者你也可以在使用getDefinition之前用方法检测是否能够成功找到某个定义。
用动态方式去获取的定义,而不是那些在当前应用程序域(及继承的程序域内)的定义,是不能用作变量类型的。就像RSL一样,在应用程序域内找不到的类定义会在校验的时候报错。所以上面的例子中boxInstance变量声明为Object类型而不是Box类型,就是因为Box类的定义在应用程序域内不存在。
Same-definition Collisions 相同定义的冲突有些时候可能会发生你引用的定义匹配到另外的应用程序域里的定义的交叉情况。这种情况将会产生如下强制转换类型错误:
TypeError: Error #1034: Type Coercion failed: cannot convert com.example::MyClass@51e1101 to com.example.MyClass.你可以看到在不同内存空间里的定义用@符号进行了区分。虽然它们内部的代码可能是完全相同的(或不同),但是由于它们存在不同的应用程序域(或安全域)内,所以它们是两个不同的定义。
只有像Object那样的原生Flash Player定义才可以将位于不同域(甚至是跨安全域的)的定义关联起来。实际上,大多数时候声明一个跨域的变量类型的时候都需要用Object类型。
虽然我们可以用Object这种通用类型来解决定义冲突错误,实际上我们更应该合理安排应用程序域的位置来消除这种不匹配的情况。
Conclusion 总结这篇教程包含了很多方面的信息。前半部分讨论了什么是安全域,以及它如何影响来自不同域的内容。Flash Player用这种安全沙箱机制保护用户的数据。Flash开发者应该了解并合理利用这种限制。
第二部分讨论了应用程序域——另一种用于在安全沙箱内划分ActionScript定义的沙箱类型。应用程序域的层级机制提供了在不同的SWF直接共享和重用定义的方法。
在安全域和应用程序域的概念上有很多容易犯的错误。希望这篇教程能够帮你对此有所准备。你不仅应当了解他们的运作方式,还要知道如何正确运用它们以达成你想要的效果。
译者注:通过这篇文章的翻译,我才真正体会了翻译工作的难做。虽然平时看英文资料的速度还挺快,但是用中文详细复述一遍需要多花好几十倍的时间。在这篇教程的翻译中,我没有使用全文翻译等辅助工具,完全靠手打,一边翻译一遍领会作者的意图。感觉收获还是比单纯看一遍要来得更多一些。