Реализация программной 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 рассматривается как особый случай.