0

私はSpringAOPをプログラムで実装することで遊んでいます。与えられたMethodInterceptorsのリストを使用してAOPObject.classプロキシを生成する単純なファクトリクラスを作成しました。

public class AOPProxyFactoryBean implements FactoryBean<Object> {

    private List<MethodInterceptor> methodInterceptors = new ArrayList<MethodInterceptor>();

    public Object getObject() throws Exception {
        Object o = new Object();
        ProxyFactory proxyFactory = new ProxyFactory(o);
        for (MethodInterceptor methodInterceptor : methodInterceptors) {
            proxyFactory.addAdvice(methodInterceptor);
        }
        return proxyFactory.getProxy();
    }

    public Class<?> getObjectType() {
        return Object.class;
    }

    public boolean isSingleton() {
        return false;
    }

    public void setMethodInterceptors(List<MethodInterceptor> methodInterceptors) {
        this.methodInterceptors = methodInterceptors;
    }

単純なインターセプター:

public class SimpleMethodInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("SimpleMethodInterceptor: " + invocation.getMethod().getName());
        return invocation.proceed();
    }
}

Spring XML構成:

<bean id="simpleMethodInterceptor" class="...SimpleMethodInterceptor"/>

<bean id="objectAOPProxyFactoryBean" class="...AOPProxyFactoryBean">
    <property name="methodInterceptors">
        <list>
            <ref bean="simpleMethodInterceptor"/>
        </list>
    </property>
</bean>

ここのドキュメントで は、addAdvice(アドバイスアドバイス)について次のように読むことができます。'...与えられたアドバイスは、toString()メソッドを含め、プロキシ上のすべての呼び出しに適用されることに注意してください!...'

したがって、SimpleMethodInterceptorによってインターセプトされたObject.classメソッドへのすべての呼び出しを取得することを期待しています。

テスト:

@Test
public void aopTest() {
    Object o = (Object) applicationContext.getBean("objectAOPProxyFactoryBean");
    o.toString();
    o.equals(o);
    o.getClass();
}

この出力を与えます:

SimpleMethodInterceptor:toString

toString()メソッドのみがインターセプトされたようです。なぜですか?

4

1 に答える 1

2

奇数。それは私にはバグのようです。理由を正確に説明することはできませんが、回避策はあります。インターフェイスを作成し、equalsとhashCodeを再定義します。

public interface MadeUpInterface {
    @Override
    public boolean equals(Object obj);

    @Override
    public int hashCode();
}

代わりに、プロキシファクトリからそのインターフェイスを実装するインスタンスを返します。

public Object getObject() throws Exception {
    Object o = new MadeUpInterface() {};
    ProxyFactory proxyFactory = new ProxyFactory(o);
    for (MethodInterceptor methodInterceptor : methodInterceptors) {
        proxyFactory.addAdvice(methodInterceptor);
    }
    return proxyFactory.getProxy();
}

これで、equalsとhashCodeが出力されます。したがって、オブジェクトでのみ定義されているメソッドの呼び出しをインターセプトしないという動作だと思います。また、toStringは特殊なケースとして扱われます。

于 2012-07-04T21:33:55.390 に答える