Rick
Rick

Reputation: 949

How to define the execution order of interceptor in Spring Boot application?

I define an interceptor and register it in a class (annotated with Configuration) which extends WebMvcConfigurerAdapter; however, I also use some third-party libraries which also define some interceptors. I want my interceptor to be the last one in the interceptor execution chain. It seems there is no way to enforce this. How to define the execution order of interceptor in Spring Boot application?

Upvotes: 20

Views: 27369

Answers (4)

LagSeeing
LagSeeing

Reputation: 73

Maybe you can use @Order on the Configurer like this.

I use springboot3.

        @Bean
        @Order(Ordered.HIGHEST_PRECEDENCE)
        MdcWebMvcConfigurer mdcWebInterceptor() {
            return new MdcWebMvcConfigurer();
        }

I read the source code, the reason why this can work is that the WebMvcConfigurers will be applied in ordered

The source code is here

@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();


    @Autowired(required = false)
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
        if (!CollectionUtils.isEmpty(configurers)) {
            this.configurers.addWebMvcConfigurers(configurers);
        }
    }
...
}

Upvotes: 0

mak
mak

Reputation: 1

All Feign clients become proxies, so there is only one way to change the order of the request interceptors. But you cannot use it, because if you change the proxy to SGLIB, it will not work.

    if(bean instanceof YoursFeignClientBean) {
        Class<Proxy> superclass = (Class<Proxy>) bean.getClass().getSuperclass();
        Field h =  superclass.getDeclaredField("h");
        h.setAccessible(true);

        // its FeignInvocationHandler
        InvocationHandler ih = (InvocationHandler) ReflectionUtils.getField(h, bean);
        Field dispatch = ih.getClass().getDeclaredField("dispatch");
        dispatch.setAccessible(true);

        Map<Method, InvocationHandlerFactory.MethodHandler> map =
                (Map<Method, InvocationHandlerFactory.MethodHandler>) dispatch.get(ih);

        for (Method method : map.keySet()) {
            InvocationHandlerFactory.MethodHandler handler = map.get(method);
            Field requestInterceptors = handler.getClass().getDeclaredField("requestInterceptors");
            requestInterceptors.setAccessible(true);

            List<RequestInterceptor> interceptorList = (List<RequestInterceptor>)
                    ReflectionUtils.getField(requestInterceptors, handler);

            RequestInterceptor ri =  interceptorList.stream().filter(t -> t.getClass().getName().startsWith(YoursFeignConfig.class.getName())).findFirst().get();

            // reorder
            interceptorList.remove(ri);
            interceptorList.add(ri);
        }

Upvotes: 0

egemen
egemen

Reputation: 839

According to my experience, Interceptors are adding a stack. For this reason you should addRegister above which one you want before calling than other.

Upvotes: -1

Sanjay K S
Sanjay K S

Reputation: 305

If we've Multiple Interceptors, Instead of @Order Annotation we can do as below.

@EnableWebMvc
@Configuration
public class WebMVCConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
            .addWebRequestInterceptor(new WebRequestInterceptor() {
                //Overrides
            }).order(Ordered.HIGHEST_PRECEDENCE);
        registry
           .addWebRequestInterceptor(new WebRequestInterceptor() {
                //Overrides
            }).order(Ordered.LOWEST_PRECEDENCE);
    }
}

Upvotes: 12

Related Questions