Spring Boot中Servlet Filter无法注入Bean的解决方法咨询
解决Spring Boot中Servlet Filter无法注入Bean的问题
问题根源
Servlet Filter默认由Servlet容器初始化,不属于Spring容器的管理范围,因此@Inject这类Spring依赖注入注解无法生效,导致AService无法被注入。
解决方案
方案一:将Filter交由Spring管理并通过FilterRegistrationBean注册
这是最规范的做法,让Spring负责Filter的实例化和依赖注入。
- 在你的依赖应用中,给
MyFilter添加Spring组件注解:
import javax.inject.Inject import javax.servlet.Filter import javax.servlet.FilterChain import javax.servlet.ServletRequest import javax.servlet.ServletResponse import org.springframework.stereotype.Component @Component class MyFilter : Filter { @Inject private lateinit var aService: AService override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) { aService.abc() chain.doFilter(request, response) } // 实现Filter接口的init、destroy方法,可留空实现 override fun init(filterConfig: javax.servlet.FilterConfig?) {} override fun destroy() {} }
- 在引入该依赖的主应用Java配置类中,用
FilterRegistrationBean注册Filter:
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.yourpackage.MyFilter; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<MyFilter> myFilterRegistration(MyFilter myFilter) { FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(myFilter); // 设置Filter匹配的URL路径,按需调整 registrationBean.addUrlPatterns("/*"); // 设置Filter执行顺序(可选) registrationBean.setOrder(1); return registrationBean; } }
Spring会自动注入MyFilter实例,其内部的AService也会被正确注入。
方案二:手动通过WebApplicationContext获取Bean
如果必须由Servlet容器直接初始化Filter,可以手动从Spring上下文获取Bean:
修改MyFilter的doFilter方法,缓存获取到的Bean避免重复查询:
import javax.servlet.Filter import javax.servlet.FilterChain import javax.servlet.ServletRequest import javax.servlet.ServletResponse import org.springframework.web.context.support.WebApplicationContextUtils class MyFilter : Filter { private var aService: AService? = null override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) { if (aService == null) { // 获取Spring Web上下文 val context = WebApplicationContextUtils.getWebApplicationContext(request.servletContext) // 方式1:按类型获取Bean(推荐,无需记忆Bean名称) aService = context?.getBean(AService::class.java) // 方式2:按名称获取Bean,@Service默认的Bean名称是首字母小写的类名,即aServiceImpl // aService = context?.getBean("aServiceImpl") as AService? } aService?.abc() chain.doFilter(request, response) } override fun init(filterConfig: javax.servlet.FilterConfig?) {} override fun destroy() {} }
注意事项
- 若
AService存在多个实现类,需通过@Qualifier注解或明确指定Bean名称/类型来区分。 - 采用方案一时,要确保主应用能扫描到依赖应用中的
@Service和@Component,可通过@ComponentScan指定依赖应用的包路径。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

