Re:AspectFlowみたいな。

個人的には Flow よりも Chain かなぁ.
そんなわけで (どんなわけで?),ちょっといかさまな実装.
まずは org.seasar.framework.aop.impl.MethodInvocationImpl を改造.(^^;
フィールド一つとコンストラクタを追加して,proceed() を修正してます.

    private MethodInvocationImpl parent_;

    public MethodInvocationImpl(MethodInvocationImpl parent, MethodInterceptor[] interceptors) {
        parent_ = parent;
        target_ = parent.target_;
        method_ = parent.method_;
        arguments_ = parent.arguments_;
        interceptors_ = interceptors;
        targetClass_ = parent.targetClass_;
        parameters_ = parent.parameters_;
    }

    public Object proceed() throws Throwable {
        while (interceptorsIndex_ < interceptors_.length) {
            return interceptors_[interceptorsIndex_++].invoke(this);
        }
        if (parent_ != null) {
            return parent_.proceed();
        }
        return methodProxy_.invokeSuper(target_, arguments_);
    }

そして InterceptorChain クラス.

public class InterceptorChain extends AbstractInterceptor {
    private MethodInterceptor[] interceptors = new MethodInterceptor[0];

    public void add(MethodInterceptor interceptor) {
        int length = interceptors.length;
        MethodInterceptor[] newArray = new MethodInterceptor[length + 1];
        System.arraycopy(interceptors, 0, newArray, 0, length);
        newArray[length] = interceptor;
        interceptors = newArray;
    }

    public Object invoke(MethodInvocation invocation) throws Throwable {
        MethodInvocation myInvocation = new MethodInvocationImpl((MethodInvocationImpl) invocation,
                interceptors);
        return myInvocation.proceed();
    }
}

テスト用の dicon ファイルを用意します.
ここではインターセプタを 3 つ持ったチェーンを一つ定義しています.ターゲットにはチェーンとその前後にインターセプタを定義しています.このため,ターゲットには合計 6 つのインターセプタが適用されていて,そのうちの 5 つが CounterInterceptor です.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
    "http://www.seasar.org/dtd/components21.dtd">
<components>
    <component name="counter" class="hoge.InterceptorChainTest$CountInterceptor"/>

    <component name="chain" class="hoge.InterceptorChain">
        <initMethod name="add"><arg>counter</arg></initMethod>
        <initMethod name="add"><arg>counter</arg></initMethod>
        <initMethod name="add"><arg>counter</arg></initMethod>
    </component>
    
    <component class="hoge.InterceptorChainTest$Foo">
        <aspect pointcut="foo">counter</aspect>
        <aspect pointcut="foo">chain</aspect>
        <aspect pointcut="foo">counter</aspect>
    </component>
</components>

テストケース.

public class InterceptorChainTest extends S2TestCase {
    public InterceptorChainTest(String name) {
        super(name);
    }

    public void setUp() {
        include("InterceptorChainTest.dicon");
    }

    public void test() {
        CountInterceptor counter = (CountInterceptor) getComponent(CountInterceptor.class);
        assertEquals(0, counter.count);

        Foo foo = (Foo) getComponent(Foo.class);
        foo.foo();
        assertEquals(5, counter.count);
    }

    public static class Foo {
        public void foo() {
        }
    }

    public static class CountInterceptor extends AbstractInterceptor {
        public int count;

        public Object invoke(MethodInvocation invocation) throws Throwable {
            ++count;
            return invocation.proceed();
        }
    }
}

一回のメソッド呼び出しで CounterInterceptor が 5 回呼び出されることを確認しています.
ばっちりでした♪

CanCam 06 月号 エビちゃんベストセレクション 2

CanCam2004年06月号の蛯原友里ちゃん

CanCam から,お気に入りの蛯原友里ちゃんを紹介しようというこのコーナー.
今日は「今,本当に欲しいのは『見た目高級,実は安い服!』これが BEST BUY!」というコーナーから P101 の友里ちゃん.
今よりふっくらして見えるような気のせいが.こうやってバックナンバー引っ張り出してくると,そんなに時間が経ったわけでもないのに結構印象が違いますね.でもでも,いつの友里ちゃんも最高にカワイイのです♪
そんなわけで (どんなわけで?),やっぱり CanCam 買うしか!!