This is by design and expected behavior. Moving custom resolvers to the top can lead to unexpected side effects.
The actual behavior is that custom resolvers are sandwiched between built-in ones and the ones that "catch-all" ones that make default assumptions. That means as long as you're using a custom type or custom annotation, it should work just fine.
Which resolver is actually trying to process your argument? I would expect none of the resolvers before the custom resolvers to do that, so it should just work.
org.springframework.web.method.annotation.MapMethodProcessor is the specific one giving me a problem. I can't use my annotation-based resolver on any Maps because that argument resolver gets chosen first.
I don't see how moving the custom argument resolvers to the beginning would cause any issues:
ensures that any custom argument resolver only gets used when the developer wants it to. I think in the general case, when people are using custom annotations or custom classes they want their resolvers to take precedence.
I don't recall the specific issues we ran into. It's been so long since this behavior was established. Generally a custom resolver would have to use a custom annotation or a custom type to avoid clashes, in which case it should make no difference. A change of behavior in terms of ordering is not an option at this point.
To address the specific issue you have, MapMethodProcessor is a bit too aggressive with a general type like Map. I can update it to check for the absence of any annotations, which is a strong indication it isn't the model that needs to be injected.