Skip to content

Avoid re-creating HandlerMethod unless handler is resolved through the BeanFactory #34277

@brucelwl

Description

@brucelwl
  1. The following code caused my custom HandlerMethod subclass to be recreated as HandlerMethod,
  2. Every HTTP request calls createWithResolvedBean(), resulting in the creation of a new instance of HandlerMethod. The handler in HandlerMethod should be determined at startup(main thread), rather than being processed after each call

https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java#L302-L323

	/**
	 * Re-create the HandlerMethod and initialize
	 * {@link #shouldValidateArguments()} and {@link #shouldValidateReturnValue()}.
	 * @since 6.1.3
	 */
	public HandlerMethod createWithValidateFlags() {
		return new HandlerMethod(this, null, true);
	}


	/**
	 * If the provided instance contains a bean name rather than an object instance,
	 * the bean name is resolved before a {@link HandlerMethod} is created and returned.
	 */
	public HandlerMethod createWithResolvedBean() {
		Object handler = this.bean;
		if (this.bean instanceof String beanName) {
			Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
			handler = this.beanFactory.getBean(beanName);
		}
		Assert.notNull(handler, "No handler instance");
		return new HandlerMethod(this, handler, false);
	}

my code

public class ControllerRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    private final List<ControllerInterceptor> controllerInterceptors;

    public ControllerRequestMappingHandlerMapping(List<ControllerInterceptor> controllerInterceptors) {
        this.controllerInterceptors = controllerInterceptors;
    }

    @Override
    protected HandlerMethod createHandlerMethod(Object handler, Method method) {
        ArrayList<ControllerInterceptor> interceptors = new ArrayList<>();
        Class<?> declaringClass = method.getDeclaringClass();
        for (ControllerInterceptor interceptor : controllerInterceptors) {
            Pointcut pointcut = interceptor.getPointcut();
            if (AopUtils.canApply(pointcut, declaringClass)) {
                interceptors.add(interceptor);
            }
        }
        if (interceptors.size() > 0) {
            if (handler instanceof String beanName) {
                return new InterceptorHandlerMethod(beanName,
                        obtainApplicationContext().getAutowireCapableBeanFactory(),
                        obtainApplicationContext(),
                        method, interceptors);
            }
            return new InterceptorHandlerMethod(handler, method, interceptors);
        }
        return super.createHandlerMethod(handler, method);
    }
}

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions