アプリケーションドメインの操作

Flash Player 9 以降、Adobe AIR 1.0 以降

ApplicationDomain クラスの目的は、ActionScript 3.0 定義のテーブルを保存することです。 SWF ファイル内のすべてのコードは、アプリケーションドメイン内に存在するように定義されます。 アプリケーションドメインは、同じセキュリティドメイン内にある複数のクラスを分離するために使用します。 それにより、1 つのクラスについて複数の定義を用意することや、子が親の定義を再利用することが可能になります。

ActionScript 3.0 で作成された外部 SWF ファイルを Loader クラス API でロードするときは、アプリケーションドメインを使用できます。 ActionScript 1.0 または ActionScript 2.0 で作成された SWF ファイルのイメージをロードするときは、アプリケーションドメインを使用できないことに注意してください。 ロードされたクラスに含まれているすべての ActionScript 3.0 定義は、アプリケーションドメイン内に格納されます。 SWF ファイルをロードするとき、LoaderContext オブジェクトの applicationDomain パラメーターを ApplicationDomain.currentDomain に設定することにより、ファイルを Loader オブジェクトと同じアプリケーションドメインに含めるよう指定できます。ロードされた SWF ファイルを同じアプリケーションドメインに置くと、そのクラスに直接アクセスできます。 これは、関連するクラス名によってアクセスできるメディアが埋め込まれた SWF ファイルをロードする場合や、ロードされた SWF ファイルのメソッドにアクセスする場合に便利です。

次の例では、welcome() という名前のパブリックメソッドを定義している別の Greeter.swf というファイルにアクセスすることを想定しています。

package 
{ 
    import flash.display.Loader; 
    import flash.display.Sprite; 
    import flash.events.*; 
    import flash.net.URLRequest; 
    import flash.system.ApplicationDomain; 
    import flash.system.LoaderContext; 
 
    public class ApplicationDomainExample extends Sprite 
    { 
        private var ldr:Loader; 
        public function ApplicationDomainExample() 
        { 
            ldr = new Loader(); 
            var req:URLRequest = new URLRequest("Greeter.swf"); 
            var ldrContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain); 
            ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler); 
            ldr.load(req, ldrContext);     
        } 
        private function completeHandler(event:Event):void 
        { 
            var myGreeter:Class = ApplicationDomain.currentDomain.getDefinition("Greeter") as Class; 
            var myGreeter:Greeter = Greeter(event.target.content); 
            var message:String = myGreeter.welcome("Tommy"); 
            trace(message); // Hello, Tommy 
        } 
    } 
}

Adobe Flash Platform 用 ActionScript 3.0 リファレンスガイド 』の ApplicationDomain クラスの例 も参照してください。

それ以外に、アプリケーションドメインを操作するときに注意すべき点は、次のとおりです。

  • SWF ファイル内のすべてのコードは、アプリケーションドメイン内に存在するように定義されます。 現在のドメインとは、メインアプリケーションが実行される場所のことです。現在のドメインなど、すべてのアプリケーションドメインは、システムドメインに含まれます。つまり、システムドメインにはすべての Flash Player クラスが含まれます。

  • システムドメインを除くすべてのアプリケーションドメインには、親ドメインが関連付けられています。 メインアプリケーションのアプリケーションドメインの親ドメインは、システムドメインです。 ロードされるクラスは、そのクラスの親によってまだ定義されていない場合にのみ定義されます。 ロードされるクラスの定義を新しい定義でオーバーライドすることはできません。

次の図に示すアプリケーションでは、様々な SWF ファイルから domain1.com という単一のドメイン内にコンテンツをロードしています。 ロードするコンテンツによっては、異なるアプリケーションドメインを使用することもできます。 このアプリケーションに含まれる個々の SWF ファイルでは、それぞれに適した異なる形態でアプリケーションドメインを使用しています。各形態の使い分け方について次に説明します。

フルサイズのグラフィックを表示
A.
使用形態 A

B.
使用形態 B

C.
使用形態 C

メインアプリケーションファイルは application1.swf です。 これには、他の SWF ファイルからコンテンツをロードする Loader オブジェクトが入っています。 このシナリオでは、現在のドメインは Application domain 1 です。使用形態 A、使用形態 B、および使用形態 C は、アプリケーション内の各 SWF ファイルに適切なアプリケーションドメインを設定する様々な手法の例を示しています。

使用形態 A
システムドメインの子ドメインを作成することにより、子 SWF ファイルを分離します。図では、システムドメインの子ドメインとして Application domain 2 を作成しています。"application2.swf" ファイルを Application domain 2 内にロードしているため、このファイルに含まれるクラス定義は "application1.swf" のクラス定義と分離されます。

この形態の用途としては、古いアプリケーションにおいて同じアプリケーションの新バージョンを動的にロードする場合に競合の発生を防ぐことが考えられます。 異なるバージョンを異なるアプリケーションドメインに分離すれば、それぞれにおいて同じクラス名を使用していても競合が発生しません。

次のコードでは、システムドメインの子ドメインとしてアプリケーションドメインを作成し、それを使用して SWF のロードを開始します。

var appDomainA:ApplicationDomain = new ApplicationDomain(); 
 
var contextA:LoaderContext = new LoaderContext(false, appDomainA); 
var loaderA:Loader = new Loader(); 
loaderA.load(new URLRequest("application2.swf"), contextA);

使用形態 B:
現在のクラス定義に新しいクラス定義が追加されます。図では、"module1.swf" に対するアプリケーションドメインとして現在のドメイン(Application domain 1)を設定しています。この場合、アプリケーションに現在含まれている各種のクラス定義に、新しいクラス定義を加えることになります。この形態は、メインアプリケーションのランタイム共有ライブラリに使用できます。 ロードされた SWF は、リモート共有ライブラリ(RSL)として扱われます。アプリケーションが開始する前にプリローダーによって RSL をロードするには、このテクニックを使用します。

次のコードでは、SWF をロードし、現在のドメインをアプリケーションドメインとして設定します。

var appDomainB:ApplicationDomain = ApplicationDomain.currentDomain; 
 
var contextB:LoaderContext = new LoaderContext(false, appDomainB); 
var loaderB:Loader = new Loader(); 
loaderB.load(new URLRequest("module1.swf"), contextB);

使用形態 C:
現在のドメインの新しい子ドメインを作成することにより、親のクラス定義を使用します。図では、"module3.swf" に対するアプリケーションドメインとして現在のドメインの子ドメインを設定しており、子ドメインでは、親ドメインに含まれるすべてのクラス定義を使用します。 この形態の用途としては、複数画面の RIA(高度なインターネットアプリケーション)を構成するモジュールをメインアプリケーションの子としてロードし、メインアプリケーションで定義されている型をモジュール内でも使用できるようにすることが考えられます。クラスを更新される際に必ず後方互換性を維持するようにし、また、ロードされるモジュールよりもメインアプリケーションを常に新しくしておけば、メインアプリケーションに含まれるクラス定義はモジュール内でも使用されます。 また、このようにして新しいアプリケーションドメイン内にロードしたモジュールは、アンロードすれば、すべてのクラス定義をガベージコレクションの対象とすることができます(ただし、子 SWF への参照を確実に破棄する必要があります)。

このテクニックでは、ロードする側にあるシングルトンオブジェクトや静的クラスメンバーを、ロードされる側のモジュールでも共有できます。

次のコードでは、現在のドメインの子ドメインを新しく作成し、そのアプリケーションドメインを使用して SWF のロードを開始します。

var appDomainC:ApplicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); 
 
var contextC:LoaderContext = new LoaderContext(false, appDomainC); 
var loaderC:Loader = new Loader(); 
loaderC.load(new URLRequest("module3.swf"), contextC);