0

我正在尝试以编程方式实现 Spring AOP。我创建了一个简单的工厂类,它使用给定的 MethodInterceptors 列表生成 AOP Object.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();
    }
}

春天 XML 配置:

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

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

在此处的文档中, 您可以阅读有关 addAdvice(Advice advice) 的以下内容:'...请注意,给定的建议将适用于代理上的所有调用,甚至适用于 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。所以我认为行为是它不会拦截对仅在 Object 上定义的方法的调用。并且 toString 被视为一种特殊情况。

于 2012-07-04T21:33:55.390 回答