Реализация программной Spring AOP с ProxyFactory

Я играю с внедрением Spring AOP программно. Я создал простой фабричный класс, который производит прокси AOP Object.class с заданным списком MethodInterceptors:

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(совет Advice): "... обратите внимание, что данный совет будет применяться ко всем вызовам прокси, даже к методу toString()!..."

Итак, я ожидаю получить все вызовы методов Object.class, перехваченные SimpleMethodInterceptor.

Тестовое задание:

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

дает этот вывод:

SimpleMethodInterceptor: toString

Кажется, что только метод toString() был перехвачен. Есть идеи почему?

1 ответ

Решение

Странный. Это похоже на ошибку для меня. Я не могу объяснить почему, но у меня есть возможный обходной путь. Создайте интерфейс и переопределите 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 рассматривается как особый случай.

Другие вопросы по тегам