Description
@Override
public int hashCode() {
return (getExecutable().hashCode() * 31 + this.parameterIndex);
}
HandlerMethodArgumentResolverComposite
uses MethodParameter
as a cache key for HandlerMethodArgumentResolver
.
Consider:
@FunctionalInterface
public interface GenericHandler<P> {
Object handle(P payload, MessageHeaders headers);
}
public static class MapHandler implements GenericHandler<Map<String, String>> {
@Override
public String handle(Map<String, String> mapPayload, MessageHeaders messageHeaders) {
return "Hello " + mapPayload.get("key");
}
}
public static class StringHandler implements GenericHandler<String> {
@Override
public String handle(String stringPayload, MessageHeaders messageHeaders) {
return stringPayload + " World!";
}
}
MethodParameter.executable
in both cases is the interface Method
:
public abstract java.lang.Object org.springframework.integration.handler.GenericHandler.handle(java.lang.Object,org.springframework.messaging.MessageHeaders)
When invoking the second method, we get a cache hit and fail with a class cast exception because the wrong argument resolver is returned.
Spring Integration recently changed to use a shared DefaultMessageHandlerMethodFactory
@Bean
, and hence a shared HandlerMethodArgumentResolverComposite
.
We can work around this by changing the bean scope to prototype, but I think the hashCode()
and equals()
should include at least the containingClass
and/or parameterType
field.