Honor BeanDefinition order attribute for DispatcherServlet strategies#36739
Open
daguimu wants to merge 5 commits intospring-projects:mainfrom
Open
Honor BeanDefinition order attribute for DispatcherServlet strategies#36739daguimu wants to merge 5 commits intospring-projects:mainfrom
daguimu wants to merge 5 commits intospring-projects:mainfrom
Conversation
Prior to this commit, the `resolveUrlPath` implementation for the `LiteWebJarsResourceResolver` would always delegate to the resource chain once the versioned webjar folder has been resolved. While this aligns with the `ResourceResolver` contract and the fact that the resource chain does not resolve directories, here the WebJar locator does support such use cases and we shouldn't get in the way here. This commit falls back to the resolved versioned WebJar path if no resource could be resolved and the path ends with "/". Fixes spring-projectsgh-36726
Prior to this commit, MIME types with parameter values that contain a quoted pair would sometimes fail and parse an incomplete parameter value. This commit ensures that the quoted section of the parameter value is correctly handled. Fixes spring-projectsgh-36730
68f63cd to
c4594f4
Compare
…trategies The strategy detection in DispatcherServlet (HandlerMappings, HandlerAdapters, HandlerExceptionResolvers, ViewResolvers) sorted matched beans with AnnotationAwareOrderComparator.sort(...) directly. That comparator only sees the bean instances and falls back to @order annotation or the Ordered interface, ignoring an order attribute set on the merged bean definition. As a result, ordering bean definitions programmatically — via BeanRegistrar.Spec#order(int), GenericApplicationContext.registerBean's order parameter, or AbstractBeanDefinition#ORDER_ATTRIBUTE directly — had no effect on these strategy lists, even though the same attribute is honored for sorted dependency injection (DefaultListableBeanFactory's FactoryAwareOrderSourceProvider). Sort each strategy list with a comparator that wraps an OrderSourceProvider. The provider mirrors FactoryAwareOrderSourceProvider: it resolves the merged BeanDefinition and exposes its ORDER_ATTRIBUTE, factory method, and declared target type as ordering sources, leaving @Order/Ordered fallback to the comparator. Non-Integer ORDER_ATTRIBUTE values are rejected with IllegalStateException, matching the bean factory's existing behavior. Behavior is unchanged for beans that do not declare ORDER_ATTRIBUTE. Closes spring-projectsgh-36637 Signed-off-by: daguimu <daguimu.geek@gmail.com>
c4594f4 to
7a05a9e
Compare
Contributor
|
Note that we've had to re-write commits in main and 7.0.x over the past 2 days after erroneous merge that this PR was based on. The PR needs to be handled with care focusing on just the one commit 7a05a9e and ignoring the other 4. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
DispatcherServletdetects four kinds of strategy beans (HandlerMapping,HandlerAdapter,HandlerExceptionResolver,ViewResolver) by type and keeps each list sorted. The sort callsAnnotationAwareOrderComparator.sort(list)directly on the matched bean instances, which only consults@Orderon the bean class and theOrderedinterface.Setting the order programmatically — via
BeanRegistrar.Spec#order(int), theorderparameter onGenericApplicationContext#registerBean(...), orAbstractBeanDefinition#ORDER_ATTRIBUTEdirectly on a bean definition — has no effect on these strategy lists, even though the same attribute is honored for sorted dependency injection throughDefaultListableBeanFactory.FactoryAwareOrderSourceProvider.Root cause
AnnotationAwareOrderComparator.sort(List)runs without anOrderSourceProvider. With no source provider, the comparator never reaches the bean definition and cannot readORDER_ATTRIBUTE.Fix
Add a private helper
sortStrategyBeansthat sorts the matched list usingAnnotationAwareOrderComparator.INSTANCE.withSourceProvider(...). TheBeanDefinitionOrderSourceProvidermirrorsFactoryAwareOrderSourceProviderexactly:BeanDefinitionviaConfigurableApplicationContext.getBeanFactory().getMergedBeanDefinition(...)(which already walks the parent BeanFactory chain).ORDER_ATTRIBUTEvalue as anOrderedsource when present andInteger.RootBeanDefinitioninstances (so@Orderon a@Beanfactory method works).IllegalStateExceptionfor a non-IntegerORDER_ATTRIBUTE, matching the bean factory's fail-fast behavior.The helper is applied at all four strategy-detection sites. Beans without
ORDER_ATTRIBUTEsee no behavior change — the comparator still falls back to@Order/Ordered.Tests Added
sortStrategyBeanshonorsORDER_ATTRIBUTEdetectsHandlerMappingsOrderedByBeanDefinitionOrderAttributeORDER_ATTRIBUTEoverrides class-level@OrderbeanDefinitionOrderAttributeOverridesAnnotationOrderForHandlerMappingsORDER_ATTRIBUTEresolved across parent contextshandlerMappingOrderFromBeanDefinitionInheritsAcrossParentContextIntegerORDER_ATTRIBUTEis rejectednonIntegerOrderAttributeIsRejectedThe tests exercise the change through
getHandlerMappings()but cover the shared helper used by all four strategies. The full:spring-webmvc:testsuite passes.Impact
spring-webmvconly; private API, no public surface added.ORDER_ATTRIBUTEto a non-Integerdirectly; public APIs only acceptint/Integer.DispatcherServlet.properties) is unaffected.DispatcherHandlerandOncePerRequestFilterordering are out of scope.Closes gh-36637