In some scenarios, we need to get HandlerMethod ahead of org.springframework.web.reactive.DispatcherHandler, such as an implement of authentication by WebFilter

public class AuthFilter implements WebFilter, Ordered {

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return handlerMapping.getHandler(exchange).switchIfEmpty(chain.filter(exchange))
            .flatMap(handler -> {
                    if (handler instanceof HandlerMethod) {
                        HandlerMethod methodHandle = (HandlerMethod) handler;
                        CheckPermission permission = methodHandle.getMethodAnnotation(CheckPermission.class);
                        if (Objects.isNull(permission)) {
                            permission = AnnotationUtils.findAnnotation(methodHandle.getBeanType(), CheckPermission.class);
                        }

                        if (Objects.nonNull(permission)) {
                            // TODO  do something..
                        }
                    }
                    return chain.filter(exchange);
                }
            );
    }
}

HandlerMethod is necessary but there is no alternative way to get it withon WebFilter, which limited the capabilities of WebFilter. so, we need call getHandler, however this may lead to repeated call of lookupHandlerMethod and unexpected execution of exchange.getAttributes().remove(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); as below:

https://github.com/spring-projects/spring-framework/blob/00da70e26b9cb5ece2a9499e7c1b449e856b4aea/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java#L293

To avoid duplicate search for HandlerMethod in mapping.getHandler , I suggest implementing a improved getHandlerInternal, in which HandlerMethod would be keep in attributes as long as it found.

    @Override
    public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
        return Mono.justOrEmpty(exchange.<HandlerMethod>getAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE))
            .switchIfEmpty(Mono.defer(() -> getHandlerAndCache(exchange)));
    }

    protected Mono<HandlerMethod> getHandlerAndCache(ServerWebExchange exchange) {
        exchange.getAttributes().remove(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
        return super.getHandlerInternal(exchange)
            .doOnNext(handler -> exchange.getAttributes().put(BEST_MATCHING_HANDLER_ATTRIBUTE, handler))
            .doOnTerminate(() -> ProducesRequestCondition.clearMediaTypesAttribute(exchange));
    }

related issue:https://github.com/spring-projects/spring-framework/issues/20123