简体   繁体   中英

How to Inject Dependencies into a Servlet Filter with Spring Boot Filter Registration Bean?

I have a Servlet Filter within my Spring Boot (2.0.1) application that I'm registering with FilterRegistrationBean which I need it to be executed first (order of one) along the filter chain. The application is deployed to JBoss 7.2 . This filter also has a dependency that is injected with @Autowired (see below):

package my.pkg.com
@SpringBootApplication
@ComponentScan(basePackages={"my.pkg.com"})
public class MyApp extends SpringBootServletInitializer {
  public satic void main(String[] args) throws IOException {
    SpringApplication.run(MyApp.class, args);
  }

  @Bean
  @Order(1)
  public FilterRegistrationBean<MyFilter> myFilter() {
    FilterRegistrationBean<MyFilter> contextFilter = new FilterRegistrationBean<>();
    contextFilter.setFilter(new MyFilter());
    contextFilter.addUrlPattern("/api/*");
    return contextFilter;
  }
}


package my.pkg.com.filter

public class MyFilter extends Filter {

  @Autowired
  private MyService mySrv;


  @Override

  public void doFilter(…) {

    mySrv.doSomething(); // mySrv is null
  }
}

The problem is when the application is deployed and ran, when the Servlet request gets to MyFilter.doFilter() , mySrv is null which means MyFilter was never scanned for dependency injections.

I can verify through debugging MyService which is a @Repository in my.package.com.repository package does get initialized. It just never gets injected into MyFilter .

I can create a constructor for MyFilter to take MyService , then @Autowired MyService into MyApp and during filter registration, I can pass it to this constructor, which resolves the issue.

However, I want to know if there is anything I'm doing wrong that this dependency doesn't get injected into MyFilter with using the setup above alone.

If you create an object by yourself, using new , and this object is not returned by a @Bean -annotated method, then it's not a Spring bean, and Spring will thus not inject anything in it.

You can just add an @Bean-annotated method returning new MyFilter() , and call that method from myFilter() to get the bean, or add a MyFilter as argument to myFilter() .

Example:

@Bean
@Order(1)
public FilterRegistrationBean<MyFilter> myFilter() {
    FilterRegistrationBean<MyFilter> contextFilter = new FilterRegistrationBean<>();
    contextFilter.setFilter(theActualFilter());
    contextFilter.addUrlPattern("/api/*");
    return contextFilter;
}

@Bean 
public MyFilter theActualFilter() {
    return new MyFilter(); // now this is a Spring bean
}

or

@Bean
@Order(1)
public FilterRegistrationBean<MyFilter> myFilter(MyFilter theActualFilter) {
    FilterRegistrationBean<MyFilter> contextFilter = new FilterRegistrationBean<>();
    contextFilter.setFilter(theActualFilter);
    contextFilter.addUrlPattern("/api/*");
    return contextFilter;
}

@Bean 
public MyFilter theActualFilter() {
    return new MyFilter(); // now this is a Spring bean
}

很简单,在过滤器类上添加@Component批注,它将使@Autowired批注在内部起作用,因为Spring依赖项注入将处理您的过滤器类并注入服务bean。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM