反復条件 (IterationCondition) のとき(→)に「@Prepare」「@Dispose」アノテーションが出てきました。 これらは事前処理・事後処理を指定するアノテーションでした。 今回以降数回にわたって、それらのアノテーションが付加されているメソッドの呼び出しを適当な箇所に「織り込ん」で見ましょう。
prepareForXxx(), disposeForXxx() メソッド
前々回、SimulationComponent オブジェクト間に論理構造を入れました。 事前処理・事後処理もこれらの論理構造を用いて、「親が子の処理を呼び出す」ようにしましょう。
具体的には、またまた「インタータイプ宣言」を用いて SimulationComponent にメソッド「prepareForSimulation()」「disposeForSimulation()」を付加します。 これらは自分に定義されている(アノテーションの付いた)メソッドの実行と、子要素の事前処理・事後処理を行います:
public aspect ComponentAspect { public void SimulationComponent.prepareForSimulation() throws SimulationException{ // @Prepare(JoinPoint.SIMULATE) // が付加されているを実行する。 for(SimulationComponent child: this.getChildComponents()) child.prepareForSimulation(); } public void SimulationComponent.disposeForSimulation() throws SimulationException{ for(SimulationComponent child: this.getChildComponents()) child.disposeForSimulation(); // @Dispose(JoinPoint.SIMULATE) // が付加されているを実行する。 } }
prepareForSimulation() では、そこに定義されている @Prepare アノテーションが付加されたメソッドを実行した後、子要素の prepareForSimulation() メソッドを呼び出しています。 一方、disposeForSimulation() では、逆に子要素の disposeForSimulation() メソッドを先に呼び出しています。
これと同じように、次のメソッドも定義しておきます*1:
- prepareForIteration(), disposeForIteration()
- prepareForEvolution(), disposeForEvolution()
シミュレーションに関する事前処理・事後処理
シミュレーションに関する事前処理・事後処理(JoinPoint が指定されていない、もしくは SIMULATE に指定されている)は、メソッド IterativeSimulator#simulate() に織り込みます。
AspectJ を用いてこれを実現するには、around アドバイスを用いて以下のように書きます:
public aspect IterativeSimulatiorComponent{ void around(IterativeSimulator sim) throws SimulationException: execution(* IterativeSimulator.simulate()) && this(sim) { try{ sim.prepareForSimulation(); proceed(sim); }finally{ sim.disposeForSimulation(); } } }
事後処理は例外が投げられても呼び出されるように、finally 節に書きます。
*1:JoinPoint オブジェクトを引数にとるメソッドを定義しておけば良さそうですが、SIMULATE と ITERATE, EVOLVE では指定される JoinPoint は扱いが少々異なるので、別々に宣言しています。 後々 ITERATE, EVOLVE のメソッドのみを上書きする必要が出てきます。