Java 如果过滤器被声明为Springbean,有没有办法告诉Spring不要注册过滤器?
我正在构建一个应用程序框架,它(作为实现的一部分)使用SpringJava 如果过滤器被声明为Springbean,有没有办法告诉Spring不要注册过滤器?,java,spring,spring-mvc,filter,Java,Spring,Spring Mvc,Filter,我正在构建一个应用程序框架,它(作为实现的一部分)使用SpringFilterRegistrationBeanbeans注册过滤器。注册方法(用@Bean注释)根据确定过滤器是打开还是关闭的某些逻辑,返回包装真实过滤器的FilterRegistrationBean,或伪ServletContextInitializer。(这样可以避免停用的过滤器使过滤器链混乱。) 现在,我希望过滤器能够感知上下文。因此,我将过滤器设置为@组件 @Component public class MyRealFilt
FilterRegistrationBean
beans注册过滤器。注册方法(用@Bean
注释)根据确定过滤器是打开还是关闭的某些逻辑,返回包装真实过滤器的FilterRegistrationBean
,或伪ServletContextInitializer
。(这样可以避免停用的过滤器使过滤器链混乱。)
现在,我希望过滤器能够感知上下文。因此,我将过滤器设置为@组件
@Component
public class MyRealFilter implements Filter {
@Autowired
private ApplicationContext applicationContext;
// stuff
}
如果过滤器处于打开状态(someLogic()
以上返回true),并且Spring仍然尊重您在FilterRegistrationBean
上指定的任何配置,那么这就可以正常工作。但是,如果关闭过滤器,过滤器仍然会被注册,因为它是@组件
。Spring似乎会自动注册任何声明为@组件的过滤器,除非该过滤器已经在FilterRegistrationBean
中注册
有没有办法告诉Spring不要注册声明为@组件的过滤器?或者我希望过滤器能够感知上下文,但仍然只能通过FilterRegistrationBean
注册,而不是直接注册,以此来解决这个问题
更新:我后来发现,如果我自己在这样一个register()
方法中构造bean,那么@ApplicationContext
实际上不会自动连接。解决这个问题的方法是将FilterRegistrationBean
的子类声明为具有@PostConstruct
的@Component
,而不是使用register()
使用@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引导如何注册筛选器、侦听器等(例如,请参见如何)。只有在首次初始化Spring上下文时,才应在运行时创建筛选器。为什么不扩展BeanFactoryPostProcessor并评估创建BeanDefinition与否之间的逻辑分支。如果逻辑的计算结果为true,则应在应用程序上下文中创建并注册BeanDefinition。顺便说一句,如果您手动将过滤器标记为@Component,则无需将其注册到spring容器中(这只是将bean注册到spring容器的一种基于注释的方法)。为了避免伪(出于某种原因),您可以创建名为Acceptable的自定义接口,并使用“accept”方法实现它。它应该返回运行时生成的聚合值(实例值)。因此,当您在FilterRegistrationBean中创建过滤器时,无论“someLogic”是什么,都应该创建它,并根据您的逻辑将值“accept”设置为true或false。稍后,后处理器应该获取这个bean,检查它是否应该被应用(通过过滤方法“accept”),如果它返回false(这取决于您如何创建它),后处理器应该使用BeanDefinitionRegistry#removeDefinition(..)从上下文中删除它。有条件地注册筛选器,这就是@ConditionalOn
内容的用途,您可以使用自己的条件表达式对其进行扩展。这不起作用,因为我无法自动连线。在您的术语中,FilterX
不能将内容自动连接到其中。这就是为什么我需要使用我在问题评论中描述的混合解决方案。不,你不需要。。。如果它是一个豆子,它会让东西自动连线。。。如果在创建过滤器注册的方法中创建过滤器,它将不起作用,但如果将其创建为bean,它将起作用。关键是您需要将两者注册为@Bean
,而不是在创建另一个的方法中创建一个。它必须像豆子一样可见。啊,对了,我明白了。这在我的头脑中是有道理的,但我将在下周进行测试。谢谢你的建议!
@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;
}
}
}