如果过滤器声明为 Spring bean,有没有办法告诉 Spring 不要注册过滤器?

Kid*_*rla 6 java spring spring-mvc filter

我正在构建一个应用程序框架(作为实现的一部分)使用 Spring FilterRegistrationBeanbean 注册过滤器。注册方法(用 注释@Bean)根据确定过滤器是否打开或关闭的某种逻辑返回FilterRegistrationBean包装真实过滤器或虚拟过滤器。ServletContextInitializer(这种方式可以避免停用的过滤器使过滤器链变得混乱。)

// This method is in some other class which is an `@Component`, and not within the same class as the `Filter` itself
@Bean
public ServletContextInitializer register() {
    if (someLogic()) {
        Filter filter = new MyRealFilter();
        FilterRegistrationBean frb = new FilterRegistrationBean(filter);
        // ... Stuff to do with configuring the filter patterns etc. ...
        return frb;
    } else {
        return new DummyServletContextInitializer(); // a SCI which does nothing
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我希望过滤器能够感知上下文。所以我将过滤器设置为@Component.

@Component
public class MyRealFilter implements Filter {
    @Autowired
    private ApplicationContext applicationContext;

    // stuff
}
Run Code Online (Sandbox Code Playgroud)

如果过滤器打开(someLogic()上面返回 true)并且 Spring 仍然尊重您在FilterRegistrationBean. 但是,如果过滤器关闭,过滤器仍然会被注册,因为它是@Component. 看起来 Spring 会自动注册任何声明为 a 的过滤器@Component,除非该过滤器已经在 a 中注册FilterRegistrationBean

有没有办法告诉 Spring 不要注册声明为 的过滤器@Component?或者有任何其他方法来解决这个问题,我希望过滤器能够感知上下文,但仍然只能通过 aFilterRegistrationBean而不是直接注册?

更新:我后来发现,@ApplicationContext如果我自己在这样的方法中构造 bean,实际上不会自动装配register()。解决这个问题的方法是使用FilterRegistrationBeana来声明@Componenta的子类@PostConstruct,而不是使用register()

M. *_*num 1

使用这些@ConditionalOn内容来确定需要注册的内容。不要将其放在过滤器或@Bean方法上,而是放在@Configuration类上。

@Configuration
public class OptionalWebFiltersConfiguration {

    @Configuration
    @ConditionalForFilterX
    public static class FilterXConfiguration {

        @Bean
        public Filter filterX() {
             return new FilterX();
        }

        @Bean
        public FilterRegistrationBean filterXRegistrationBean() {
             FilterRegistrationBean frb = new FilterRegistrationBean frb = new FilterRegistrationBean(filterX());
             // other config
             return verb;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这将仅包括满足条件时的过滤器配置,而不包含重复的条件指令。这也是 Spring Boot 注册过滤器、监听器等的方式(例如,参见如何DispatcherServlet注册)。

  • 不,你不...如果它是一个bean,它会自动连接...如果您在创建过滤器注册的方法中创建过滤器,它将不起作用,但如果您将其创建为bean,则它会起作用会工作。关键是您需要将两者注册为“@Bean”,而不是在创建另一个的方法中创建一个。它必须以 bean 的形式可见。 (2认同)