`

AS3应用程序模块化开发与ApplicationDomain

    博客分类:
  • AS
阅读更多

AS3应用程序模块化开发与ApplicationDomain

                当程序越来越大,我们需要把它拆分成多个swf,在需要的时候动态加载。拆分时应该尽量把不同的类编译进唯一的swf,避免因swf文件增多而使整个程 序的文件尺寸增大。 按此原则可以拆分出以下两种swf,借助 ApplicationDomain 共享其代码和资源。

        模块(Module)

                按照程序逻辑,可以拆分出多个“功能模块”,如“注册”、“管理”等等;按照游戏或社区类程序的关卡或场景,可以拆分出不同的“场景模块”。
                这些模块不是主程序运行必须的,只在需要的时候加载
        运行时共享库(RSL)
                主场景或者多个模块通用的资源 ,比如位图、声音、设计好的页面元素等,可作为“库”在主程序运行前加载。可以整套更换的皮肤(skin)只需先加载一套。
  
----------------------------------------------
       applicationDomain 属性
   public var applicationDomain:ApplicationDomain = null

       指定用于 Loader.load()Loader.loadBytes() 方法的应用程序域。 只应在加载使用 ActionScript 3.0 编写的 SWF 文件(不是图像或使用 ActionScript 1.0 或 ActionScript 2.0 编写的 SWF 文件)时才使用此属性。

       每 个安全域被分成一个或多个由 ApplicationDomain 对象表示的应用程序域。 应用程序域并不是用于安全目的;它们用于管理 ActionScript 代码的协作单元。 如果是从其它域加载 SWF 文件,并允许将它放置到另外一个安全域中,则您将无法控制所加载的 SWF 文件被放置到哪个应用程序域中;即使您指定应选择某个应用程序域,也会忽略。 但是,如果是将 SWF 文件加载到您自己的安全域中(因为此 SWF 文件来自您自己的域,或者您正在将它导入到您的安全域中),您就可以控制为所加载的 SWF 文件选择哪个应用程序域。

        在 LoaderContext.applicationDomain 中,您只可以传递您自己的安全域中的应用程序域。 如果试图传递任何其它安全域中的应用程序域,则会引发 SecurityError 异常。

        有四种 ApplicationDomain 属性可供您选择使用:

        加载器的 ApplicationDomain 的子级(模块) 默认值。 可以使用语法 new ApplicationDomain(ApplicationDomain.currentDomain) 显式表示这种选择。 这将允许所加载的 SWF 文件直接使用父级的类 ,例如,可通过编写 new MyClassDefinedInParent() 来使用。 但是父级则不能使用此语法;如果父级要使用子级的类,它必须调用 ApplicationDomain.getDefinition() 来检索它们。  
        这种选择的优点是:
        1、如果子级定义的类与父级已经定义的类同名,不会出现错误结果;
        2、子级只会继承父级对该类的定义,除非子级或父级调用 ApplicationDomain.getDefinition() 方法来检索子级的冲突定义,否则将不使用此定义。

        加载器自己的 ApplicationDomain (共享库) 使用 ApplicationDomain.currentDomain 时请使用此应用程序域。 加载完成后,父级和子级可以直接使用对方的类。  
        如果子级试图定义的类与父级已经定义的类同名,将出现错误并放弃加载。

        系统 ApplicationDomain 的子级(独立运行的程序或模块 ) 。 使用 new ApplicationDomain(null) 时请使用此应用程序域。 这将完全分离加载方和被加载方,从而允许它们使用相同的名称定义各自版本的类并且不会产生冲突或隐藏。 一方查看另一方的类的唯一方式是调用 ApplicationDomain.getDefinition() 方法。

        其它 ApplicationDomain 的子级。 有时可能会有更复杂的 ApplicationDomain 层次结构。 可以将 SWF 文件从您自己的 SecurityDomain 加载到任何 ApplicationDomain 中 。 例如,new ApplicationDomain(ApplicationDomain.currentDomain.parentDomain.parentDomain) 将 SWF 文件加载到当前域父级的父级的新子级中。

        加载完成后,为调用 ApplicationDomain.getDefinition() ,任一方(加载方或被加载方)都可能需要找到它自己的 ApplicationDomain 或另一方的 ApplicationDomain。 任一方都可以通过使用 ApplicationDomain.currentDomain 来检索对它自己的应用程序域的引用。 执行加载的 SWF 文件可以通过 Loader.contentLoaderInfo.applicationDomain 来检索对被加载的 SWF 文件的 ApplicationDomain 的引用。 如果被加载的 SWF 文件知道自己的加载方式,则它可以找到执行加载的 SWF 文件的 ApplicationDomain 对象。 例如,如果子级是以默认方式被加载的,则它可以通过使用 ApplicationDomain.currentDomain.parentDomain 找到执行加载的 SWF 文件的应用程序域。

 ----------------------------------------------
         ApplicationDomain 是存放AS3定义(包括类、方法、接口等)的容器。
        使用Loader类加载swf时可以通过指定ApplicationDomain 参数将swf加载到不同的域(Domain):
 
         var loader : Loader = new Loader () ;
         var context : LoaderContext = new LoaderContext () ;
         /* 加载到子域(模块) */
        context . applicationDomain = new ApplicationDomain ( ApplicationDomain . currentDomain ) ;
        /* 加载到同域(共享库) */
        context . applicationDomain = ApplicationDomain . currentDomain ;
        /* 加载到新域(独立运行的程序或模块) */
        context . applicationDomain = new ApplicationDomain () ;
        loader . load ( new URLRequest ( " loaded.swf " ) , context ) ;

   ApplicationDomain使用类似于显示列表(DisplayList)的树形结构。 相对于舞台(Stage) ,可以认为 ApplicationDomain 最根部的是系统域(system domain),包含 Flash Player 核心类定义。主程序所在的域(以下简称主域)就是它唯一的子域,类似于Stage下的文档类(Document Class)。
  
        一个fla文档类里代码:
        this . stage . addChild ( mySprite ) ;
        this . addChild ( myMC ) ;
        this . addChild ( myShape ) ;

  运行后的显示列表:

  ApplicationDomain 的类似结构:

         加载到子域(模块)
         类似于“继承”,子域可以直接获得父域所有的类定义,反之父域得不到子域的。和继承关系不同的是,如果子域中有和父域同名的类,子域定义会被忽略而使用父域的定义。

        加载到同域(运行时共享库)
        类似集合里的合并关系。被加载swf里的所有类定义被合并到当前域中可以直接使用。和加载到子域相同,和当前域同名的定义也会被忽略。

        加载到新域(独立运行的程序或模块)
        swf载入指定域之前,先要检查该域及其父域中是否存在同名类,重复定义一概忽略。如果加载别人写的程序,或者使用旧版本的主程序加载新版本的模块,为避免类名冲突就要加载到新域独立运行以使用自己的类。

  模块加载到同域不是一样可以吗?为何要加载到子域呢?好处就在于,卸载一个加载到子域的模块时,只要确保清除所有到该模块的引用,模块的所有类定义将被垃圾回收(Garbage Collection)。
  有两种方式可以访问 ApplicationDomain :

  • ApplicationDomain.currentDomain
    currentDomain是ApplicationDomain的静态变量,表示当前代码 所 在的域。该变量很奇特,在主程序里指向主域,在加载到子域的模块里则指向该模块所在的子域。虽然 ApplicationDomain 有个 parentDomain 属性,但子域已经自动获得了父域的类定义,所以通过 ApplicationDomain.currentDomain 就可以获取父域定义了——包括主程序和加载到主域的共享库。(注:系统域不可直接访问,主域和所有新域即系统域子域的parentDomain属性为 null)
  • LoaderInfo类的applicationDomain属性
    此方式可以访问任何方式加载的swf的 ApplicationDomain。对于主程序来说,加载到同域的库定义已经存在于 ApplicationDomain.currentDomain ,而模块的类主程序一般用不到。所以这种方式个人不推荐使用。

  ApplicationDomain 的 hasDefinition() 方法判断某定义是否存在,getDefinition() 方法获取指定的定义。下面以一个例子来介绍 ApplicationDomain 的具体用法和应用程序的拆分。
  本利有四个swf,shell.swf是主程序,lib.swf是共享库,login.swf和result.swf分别是“登录”和“结果”模块所有的视图元件都在共享库中。
       
实际开发时可能有很多库,比如“位图库”、“音效库”、“模型通用库”等。“通用库”里存放多个模块共用的资源,比如此例中的背景元素。
        而各个模块独有的资源还是放在各自的swf中。
   主程序首先将共享库加载到同域,完成后将“登录模块”加载到子域。主程序可以像操作普通的视觉对象(DisplayObject)一样操作加载的模块: 监听事件、调用方法。因为编译器不会识别未定义的类,为使用强类型,建议为主类和模型定义相应的接口,使用少量的重复代码协助编程。

private function showModule ( p_module : IModule ) : void
{
    
if ( this . m_moduleList [ 0 ] == " login.swf " )
    
{
        
p_module . show ( this ) ;
        
p_module . addEventListener ( " login " , this . onLogin ) ;
    
} else
    
{
        
p_module . show ( this , this . m_userName ) ;
    
}
}
 

  模块“继承”了主程序和共享库的所有类和资源,可以通过 ApplicationDomain.currentDomain.getDefinition() 来获取相应的类。注意获取不存在的类会抛出一个 ReferenceError。

protected function getClass ( p_name : String ) : Class
{
    
try
    
{
        
return ApplicationDomain . currentDomain . getDefinition ( p_name ) as Class ;
    
} catch ( p_e : ReferenceError )
    
{
        
trace ( " 定义 " + p_name + " 不存在 " ) ;
        
return null ;
    
}
    
return null ;
}
 

  登录模块获取库中的界面元素,并在点击按钮后抛出事件。Event类不允许带参数,必须使用继承Event的自定义事件抛出参数。 主程序可以把模块的自定义事件也编译进去(这样就增大了整个程序的文件尺寸),或者让监听模块事件的函数接受一个Objcet参数,以获取其动态属性。

private function onLogin ( p_e : Object ) : void
{
    
this . m_userName = p_e . userName ;
    
var login : IModule = p_e . currentTarget ;
    
login . removeEventListener ( " login " , this . onLogin ) ;
    
login . dispose () ;
    
this . loadSwf () ;
}
 

  主程序收到事件之后卸载注册模块,加载“结果模块”到子域,并将登录模块传出的”userName”参数传给结果模块。

public function show ( p_parent : DisplayObjectContainer , ... rest ) : void
{
    
var libClass : Class = this . getClass ( " net.eidiot.appDomainDemo.Libaray " ) ;
    
if ( libClass != null ) this . initUi ( libClass , rest ) ;
}
override protected function initUi ( p_libClass : Class , p_rest : Array = null ) : void
{
    
this . addUi ( this . getClass ( p_libClass . BG_NAME ) , " 结果 " ) ;
    
var resultFunc : Function = p_libClass . getResult ;
    
var userName : String = p_rest [ 0 ] ;
    
this . addChild ( resultFunc ( userName )) ;
}
 

  注意initUi()方法分别使用了共享库中Libaray类的静态属性BG_NAME和静态方法getResult()。但是直接调用此静态方法会报错,可以先用 resultFunc 变量取出此方法。详细内容请参考 源代码

       实例效果演示
       下载源文件 (rar 278K)
分享到:
评论

相关推荐

    Flex ApplicationDomain

    模块可以看作是独立的应用程序,它们有自己的ApplicationDomain,可以加载不同的类集,这使得模块化开发更加灵活,也便于版本控制和更新。 举个例子,如果你正在开发一个Flex应用程序,而该程序需要加载第三方库,...

    jboss-as-web.Final-RECOMPILE.jar.rar

    JBoss AS 7通过其模块化架构实现了热部署,使得开发者可以实时更新Web应用程序,而无需重启服务器。 1. **热部署原理**:在传统的Java应用服务器中,更新部署的Web应用通常需要重启服务器。然而,JBoss AS 7引入了...

    AS3 调用SWF类库

    在AS3(ActionScript 3)中,调用SWF类库是一项常见的任务,尤其在构建可重用组件、模块化开发或者加载外部资源时。本文将深入探讨如何使用AS3来加载和交互SWF类库,以及相关的重要知识点。 首先,让我们了解SWF是...

    JBoss AS7教程

    1. 模块化架构:JBoss AS7采用了全新的模块化设计,将各种组件和服务分离,提高了系统的可扩展性和性能。 2. 内存中的类加载器:通过优化类加载机制,实现更快的应用启动和更小的内存占用。 3. 基于AIO的网络栈:...

    jboss-as-master

    JBoss Application Server(简称JBoss AS)是Red Hat公司开发的一款开源Java EE应用服务器,它基于Eclipse MicroProfile和Jakarta EE标准,为开发和部署企业级应用程序提供了全面的平台。JBoss AS是Java世界中的重要...

    jboss server工具

    4. 模块化架构:JBoss Server采用模块化设计,使得不同功能模块之间解耦,便于维护和扩展。 5. 数据源管理:JBoss Server能够配置和管理数据源,无缝连接到各种数据库系统。 6. JMS支持:集成Java消息服务(JMS)...

    JBoss_Application_Server_7.1官方文档.pdf

    JBoss AS 7.1的主要特点包括高性能、模块化架构、可扩展性以及与云计算环境的良好集成。 在JBoss AS 7.1的官方文档中,主要内容被分为几个关键部分,以便于不同角色的用户,包括管理员、开发者以及有兴趣快速上手的...

    jboss7 文档

    JBoss AS 7(Application Server 7)是JBoss企业级中间件的一部分,由Red Hat开发并维护,是一个开源的Java应用服务器。它支持最新的Java EE 6规范,提供了包括Web容器、EJB容器、JPA、JMS、JTA在内的多种服务,为...

    jboss7 + EJB3

    - **模块化架构**:JBOSS7采用全新的模块化设计,提高了启动速度和内存效率。 - **HTTP/2支持**:提供对HTTP/2协议的支持,提升网络通信性能。 - **更强大的管理工具**:通过HornetQ和Infinispan提供更强大的消息...

    jboss集群配置方式及使用

    JBoss AS 5采用了模块化的设计思想,这种设计使得服务器可以灵活地根据需求加载不同的组件。这种架构设计不仅提高了服务器的性能,同时也简化了管理和配置过程。 - **部署类型**:JBoss AS 5支持多种可部署的应用...

    Jboss In Action

    JBoss还提供了模块化系统,允许你管理应用程序的依赖关系。理解如何组织和声明模块,以及如何在`module.xml`文件中配置它们,是提升JBoss使用效率的关键。在这个压缩包中,可能会包含不同模块的示例,帮助你学习这一...

    ArcGIS_FlexView指南(中文)

    Sample Flex Viewer采用了模块化的设计理念,主要包括以下几个核心组件: - **Widget Programming Model:** 这个模型定义了如何开发微件(Widget),包括它们的生命周期管理、数据绑定以及与其他微件之间的通信机制...

    Myclouds基础开发文档

    - **JDK**:Java Development Kit,即Java开发工具包,是开发Java应用程序的基础,包括Java编译器、Java虚拟机及Java工具等。 - **Maven**:一种项目管理工具,用于构建、管理和理解大型项目的结构。通过Maven可以...

    JBoss学习全集多本书整合

    JBoss,作为一个开源的应用服务器,基于Java EE(现在被称为Jakarta EE)标准,为开发和部署企业级应用程序提供了强大支持。本学习资料旨在帮助读者从零开始,逐步熟悉并精通JBoss的使用。 首先,配置是JBoss学习中...

    专业技术人员继续教育(初、中级)考试答案终版.pdf

    34. API:应用程序接口(Application Programming Interface),是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力。 35. IPv6/6LoWPAN:是针对低功耗局域网(Low-Power ...

    tomcat、jboss 连接池配置

    JBoss AS (Application Server) 是另一个流行的Java应用服务器。下面介绍如何在JBoss上配置连接池。 #### 1. 添加JDBC驱动 在JBoss的`modules`目录下创建一个新的模块,用来存放JDBC驱动。例如,对于Oracle数据库...

Global site tag (gtag.js) - Google Analytics