MMIH: Use Original Method for InvocableHandMethod

The `MessagingMethodInvokerHelper` extracts `targetClass` to process methods and avoid extra methods when class is Proxy

The `InvocableHandlerMethod` is based on the reflection method invocation and we should use runtime methods on the proxy to invoke.
We don't see such a problem in SpEL because it is parsed from the plain String to the real code later

Polishing

Add an Advice to the test.
This commit is contained in:
Artem Bilan
2017-02-07 12:30:33 -05:00
committed by Gary Russell
parent 5987f2e3b9
commit 8276bf8eae
2 changed files with 43 additions and 1 deletions

View File

@@ -527,6 +527,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
}
HandlerMethod handlerMethod1;
try {
method1 = org.springframework.util.ClassUtils.getMostSpecificMethod(method1, targetObject.getClass());
InvocableHandlerMethod invocableHandlerMethod =
this.messageHandlerMethodFactory.createInvocableHandlerMethod(targetObject, method1);
handlerMethod1 = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
@@ -626,9 +627,11 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
}
}
if (frameworkMethods.size() == 1) {
Method method = org.springframework.util.ClassUtils.getMostSpecificMethod(frameworkMethods.get(0),
targetObject.getClass());
InvocableHandlerMethod invocableHandlerMethod =
this.messageHandlerMethodFactory.createInvocableHandlerMethod(targetObject,
frameworkMethods.get(0));
method);
HandlerMethod handlerMethod = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
handlerMethods.put(CANDIDATE_METHODS, Collections.singletonMap(Object.class, handlerMethod));
handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
@@ -671,6 +674,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
}
Method method = targetMethod.get();
if (method != null) {
method = org.springframework.util.ClassUtils.getMostSpecificMethod(method, targetObject.getClass());
InvocableHandlerMethod invocableHandlerMethod =
this.messageHandlerMethodFactory.createInvocableHandlerMethod(targetObject, method);
HandlerMethod handlerMethod = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);

View File

@@ -23,6 +23,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
@@ -32,7 +33,10 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.aopalliance.intercept.MethodInterceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hamcrest.Description;
@@ -42,6 +46,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.expression.spel.SpelCompilerMode;
@@ -54,7 +59,9 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.util.MessagingMethodInvokerHelper;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.util.StopWatch;
@@ -761,6 +768,37 @@ public class MethodInvokingMessageProcessorTests {
}
@Test
public void testProxyInvocation() {
final AtomicReference<Object> result = new AtomicReference<>();
class MyHandler implements MessageHandler {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
result.set(message.getPayload());
}
}
MessageHandler service = new MyHandler();
final AtomicBoolean adviceCalled = new AtomicBoolean();
ProxyFactory proxyFactory = new ProxyFactory(service);
proxyFactory.addAdvice((MethodInterceptor) i -> {
adviceCalled.set(true);
return i.proceed();
});
service = (MessageHandler) proxyFactory.getProxy(getClass().getClassLoader());
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, "handleMessage");
processor.processMessage(new GenericMessage<>("foo"));
assertEquals("foo", result.get());
assertTrue(adviceCalled.get());
}
private DirectFieldAccessor compileImmediate(MethodInvokingMessageProcessor processor) {
// Update the parser configuration compiler mode
SpelParserConfiguration config = TestUtils.getPropertyValue(processor,