Spring Boot非组件过滤器中如何访问Spring组件?
Spring Boot非组件过滤器中注入组件的解决方案
下面提供几种可行的解决方法,按需选择:
方法一:构造函数注入(推荐)
因为你的过滤器是手动实例化的,Spring无法自动完成字段注入,所以可以把需要的组件通过构造函数传入:
- 修改过滤器代码,添加带组件参数的构造函数:
public class SecurityAuthorizationFilter extends BasicAuthenticationFilter { private final MyDbLogComp myDbLogComp; // 通过构造函数接收组件实例 public SecurityAuthorizationFilter(AuthenticationManager authenticationManager, MyDbLogComp myDbLogComp) { super(authenticationManager); this.myDbLogComp = myDbLogComp; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { // 直接使用myDbLogComp,不再为null myDbLogComp.logOperation("授权校验"); // 原有业务逻辑 filterChain.doFilter(request, response); } }
- 在注册过滤器的配置类中,注入目标组件并传给过滤器:
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyDbLogComp myDbLogComp; @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore( new SecurityAuthorizationFilter(authenticationManagerBean(), myDbLogComp), UsernamePasswordAuthenticationFilter.class ); // 其他安全配置项 } }
方法二:将过滤器转为Spring组件
把过滤器标记为Spring管理的组件,让Spring自动完成注入:
- 给过滤器添加
@Component注解,同时用构造函数注入组件:
@Component // 标记为Spring组件 public class SecurityAuthorizationFilter extends BasicAuthenticationFilter { private final MyDbLogComp myDbLogComp; // Spring 4.3+版本可省略@Autowired注解 @Autowired public SecurityAuthorizationFilter(AuthenticationManager authenticationManager, MyDbLogComp myDbLogComp) { super(authenticationManager); this.myDbLogComp = myDbLogComp; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { myDbLogComp.logOperation("授权校验"); filterChain.doFilter(request, response); } }
- 在配置类中注入过滤器Bean并注册:
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SecurityAuthorizationFilter securityAuthorizationFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(securityAuthorizationFilter, UsernamePasswordAuthenticationFilter.class); // 其他安全配置项 } }
方法三:手动从Spring上下文获取Bean(不推荐)
如果无法修改过滤器构造函数,可以通过Servlet上下文获取Spring容器,再手动获取组件实例。这种方式耦合度高,不利于单元测试,仅作为临时方案:
public class SecurityAuthorizationFilter extends BasicAuthenticationFilter { private MyDbLogComp myDbLogComp; public SecurityAuthorizationFilter(AuthenticationManager authenticationManager) { super(authenticationManager); } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { // 延迟初始化组件 if (myDbLogComp == null) { WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext()); if (context != null) { myDbLogComp = context.getBean(MyDbLogComp.class); } } // 使用组件 myDbLogComp.logOperation("授权校验"); filterChain.doFilter(request, response); } }
内容的提问来源于stack exchange,提问作者chris01
相关产品推荐
相关产品推荐

