連載
» 2004年12月17日 12時00分 公開

アスペクト指向のバリエーション解説(2):AspectJから学ぶアスペクト指向の理解 (1/3)

 第1回「アスペクト指向の基礎とさまざまな実装」ではアスペクト指向とAOPの概要について解説したが、今回からはAOPのさまざまな実装を取り上げていきたい。まず始めに紹介するのはAspectJである。

[米山学(クロノス 専務取締役),@IT]

AspectJのインストールと設定

 AspectJはもともとXeroxのPalo Alto 研究所で開発されていたAOPの実装であり、現在はeclipse.orgの開発プロジェクトに受け継がれて活発に開発活動が続けられている。AspectJはJava言語を拡張したような言語仕様とライブラリ、コンパイラなどのツール群から構成されている。

 ではここから実際にAspectJをインストールし、基本的な実装方法をみながら、アスペクト指向の特徴(例えば「ロギング」)や振る舞いを検証していこう。

ALT 図1 AspectJの構成

 AspectJのツール群にはコンパイラが含まれているが、実行環境は含まれていない。なぜなら、AspectJのコンパイラによって生成されたクラスファイルは通常のJavaの実行環境で動かすことができるからである。またAspectJはeclipseをはじめとしたさまざまなIDEツールをサポートしており、AOPによる開発の生産性を高めることが可能だ。この記事の最後でもAJDTと呼ばれるeclipse用プラグインの導入を紹介する。

 先述したように、AspectJは現在eclipse.orgの下で「aspectj project」として開発されている(technology projectのサブプロジェクト)。

 まずはAspectJをダウンロードしてインストールするところから始めよう(この原稿執筆時の最新リリースは「AspectJ 1.2.1 rc1」であり、本稿でもそのバージョンを使って説明をしていく)。

 「aspectj project」のページより、左側にあるメニューからDownloadsのリンクをクリックする。そして「Latest Stable Release」である「aspectj-1.2.1rc1.jar」を任意のディレクトリにダウンロードする。このJARファイルはインストーラとなっているため、Windowsでjavaw.exeに関連付けされていればJARファイルをダブルクリックするだけでインストールが開始される。コマンドプロンプトから起動するのであれば、次のようにjavaコマンドを実行すればよい。

java -jar aspectj-1.2.1rc1.jar

 JARファイルを実行するとAspectJのインストーラが起動するので、以下のようにインストールウィザードを進めていく。

ALT インストーラ起動。[Next]をクリック(クリックすれば拡大)
  1. インストーラ起動。[Next]をクリック
  2. J2SEのインストールディレクトリが検出される。問題なければそのまま[Next]をクリック
  3. AspectJのインストール先ディレクトリが表示される(デフォルトではC:\aspectj1.2)。変更しないのであればそのまま[Install]をクリック
  4. インストールが開始される
  5. インストール完了。[Finish]をクリック

 ここまででAspectJのインストールは完了である。デフォルトではC:\に「aspectj1.2」というディレクトリが作成され、その配下にライブラリやツールなどの構成ファイルが展開される。

C:\aspectj1.2
├ bin… 各種ツール群
├ lib…ライブラリ
└ doc…ドキュメント


 コンパイラなどのツールはbinディレクトリに格納されているため、インストールが完了後に「bin」ディレクトリを環境変数PATHに追加しておこう。

AspectJ版HelloWorld

 新しいテクノロジを試してみる際には、まずはできるだけシンプルで簡単なものを題材にすることが望ましい。プログラミングの世界では取っ掛かりのプログラムとして「HelloWorld」が有名であるが、ここでもAspectJ版HelloWorldプログラミングを紹介しよう。

 次のリスト1に示すプログラム「Messenger」はごく普通のJavaのプログラムである。このクラスにはprintMessage()というメソッドが1つだけ定義されている。このメソッドは引数に受け取った文字列のメッセージを画面に表示するだけの単純なstaticメソッドである。

public class Messenger {
    public static void printMessage(String message) {
        System.out.println(message);
    }
}

リスト1 Messengerクラス

 この「Messenger」クラスを呼び出すテスト用クラスは次のリスト2のようになる。

public class Tester {
    public static void main(String[] args) {
        Messenger.printMessage("AspectJ");
    }
}

リスト2 Testerクラス

 プログラムを見れば分かるように、Testerクラスを実行すれば単純に「AspectJ」という文字列が画面に表示されるだけである。普通にjavacを使ってコンパイルし、実行すれば次のように「AspectJ」と表示される。

> java Tester
AspectJ


 では、この単純なアプリケーションに「アスペクト」を適用してみよう。AspectJではアスペクトを適用することを「ウィーブ(Weave)」あるいは「ウィービング(Weaving)」と呼んでいる。Weaveとは「織り込む」という意味であり、「Cross-Cutting Concern(横断的関心事)」であるアスペクトを「Core Concern(中心的関心事)」に、文字通り織り込むことを意味する。

ALT 図2 アスペクトのウィービング

 このサンプルプログラムでウィーブするのは、メッセージの前に「Hello,」という文字列を挿入する「アスペクト」である。具体的にはMessengerクラスのprintMessage()メソッドが出力する文字列の先頭に「Hello, 」を追加するというものである。


 どちらかといえばこのようなアスペクトは機能要件(ビジネスロジック)に近く、適切なアスペクトとはいえないかもしれない。AOPでは機能要件以外の関心事、例えばロギング機能やキャッシュ機能などがアスペクトとして抽出されることが一般的であるが、ここでは導入の単純なサンプルということでその辺りには目をつぶっていただきたい。


 では実際に「アスペクト」を作成してみよう(リスト3)。AspectJの言語仕様ではアスペクトの定義にキーワード「aspect」を用いる。ファイルの拡張子は通常のJavaプログラム同様に「.java」で構わない。このアスペクトには「GreetingAspect」と名付けることにしよう。

public aspect GreetingAspect {

    pointcut message() : call(* Messenger.printMessage(..));

    before() : message() {
        System.out.print("Hello, ");
    }
}

リスト3 GreetingAspect

 このアスペクトコードは通常のJavaプログラムのようにも見えるが、「aspect」や「pointcut」といった、Java言語には定義されていないキーワードや構文を使っていることが分かる。これらはAspectJの言語仕様で定義されているキーワードである。このように、AspectJによるAOPではAspectJの言語仕様に従ったアスペクトを記述することになる。しかしAspectJの言語仕様はJava言語を拡張するような形で定義されているため、Javaのプログラマであればそれほど違和感なくAspectJプログラムを書くことができるだろう。

 アスペクトが作成できたらコンパイルしよう。AspectJではバイトコードに対してアスペクトをウィービングするため、通常のJavaコンパイラではなく専用のコンパイラが必要となる。AspectJには「ajc」と呼ばれるコンパイラが付属しており、このajcによってコンパイルされたクラスファイルが「アスペクトウィービング済み」のクラスファイルとなる。


 AspectJを使ったプログラムのコンパイルにはAspectJのライブラリが必要である。クラスパスに「lib\aspectjrt.jar」を設定してからコンパイルしよう。ajcによるコンパイルの方法もjavacを使ったコンパイルと変わりはなく、コマンドプロンプトから「ajc ソースファイル名」のようにコマンドを実行する。


> ajc *.java

ajcを使ったコンパイル

 コンパイルの結果、生成されるのは通常のクラスファイルである。次のように普通にjavaコマンドを実行すればよい。「Hello, AspectJ」と表示されるはずである。

> java Tester
Hello, AspectJ


 ここで実行結果に注目してほしい。TesterクラスやMessengerクラスのコードは一切変更していないにもかかわらず(つまりHello,という文字列の追加は行っていない)、実行結果には「Hello,」の文字が先頭に記述されている。GreetingAspectによって「Hello,」を追加する処理がウィービングされていることが分かる。

 もしAspectJを使わずに同じような結果を望むのであれば、つまり「Hello,」という文字列を先頭に加えるようにprintMessage()メソッドの振る舞いを変更するのであれば、次のようなコード修正が必要である(赤字部分)。

public class Messenger {
    public static void printMessage(String message) {
        System.out.println( "Hello, " + message);
    }
}

リスト4 Messengerクラス(AspectJを使わない例)

 しかし、AspectJを使うことで、Messengerクラスには一切手を入れることなく機能追加を実現できている。このように元のソースコードにできるだけ手を入れたくない状態で機能追加できるということはAOPの大きな特徴の1つである。

       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ