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:
committed by
Gary Russell
parent
5987f2e3b9
commit
8276bf8eae
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user