我正在构建一个应用程序框架,它(作为实现的一部分)使用Spring FilterRegistrationBean
bean注册过滤器。注册方法(用@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
}
}
现在,我希望过滤器具有上下文感知能力。所以我将过滤器设置为@Component
。
@Component
public class MyRealFilter implements Filter {
@Autowired
private ApplicationContext applicationContext;
// stuff
}
如果打开过滤器(上面的someLogic()
返回true),这可以正常工作,而Spring仍然尊重您在FilterRegistrationBean
上指定的任何配置。但是,如果关闭过滤器,过滤器仍然会被注册,因为它是@Component
。似乎Spring会自动注册声明为@Component
的任何过滤器,除非该过滤器已在FilterRegistrationBean
中注册。
有没有办法告诉Spring不要注册声明为@Component
的过滤器?或者任何其他方法来解决这个问题,我希望过滤器能够识别上下文,但仍然只能通过FilterRegistrationBean
而不是直接注册?
更新:我后来发现,如果我在@ApplicationContext
方法中自己构造bean,实际上register()
无法自动装配。解决这个问题的方法是将FilterRegistrationBean
的子类声明为@Component
@PostConstruct
,而不是使用register()
。
答案 0 :(得分: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;
}
}
}
这将仅在满足条件时包括过滤器配置,而不包含重复条件指令。这也是Spring Boot注册过滤器,监听器等的方式(例如参见DispatcherServlet
is registered)。