爲何實現了 Filter 的類,能自動添加到 filterChain 中?

當自定義 filter 時候,要把你的類實現 Filter 接口,或繼承它的子類。然後通過 FilterRegistrationBean 註冊到 filterChain 中。
你可能沒有注意這個細節,就算不做後面那一步,你的 Filter 類也能夠自動添加到 filterChain 中。

這是怎麼做到的呢?在 ServletContextInitializerBeans 中,有這麼一個方法:

被標的兩行,在初始過程中有特殊的行爲:只要類實現 Servlet 或 Filter 接口,如果沒有找到 register bean 就會自動爲其創建一個 register bean,後面就會具有 servlet 或 filter 的行爲。

這個細節有什麼用?

如果你在寫一個框架,並且框架中寫了一個 Filter, 而不加思索地在這個類上加了 @Service 或 @Component 註解,那麼它就變成了一個不可繞過的 filter. 對於框架使用者,就會很痛苦,不想用這個 filter 也不行,甚至想重寫它的行爲也做不到!因此,爲了可擴展和兼容性,使你的框架變得更友好,最好是把它變成 bean 的半成品,不加 @Service 或 @Component 註解,後面在 configuration 中通過 @Bean 的方式定義這個 bean, 以實現可控的初始化。在定義 @Bean 的時候,可以通過 @ConditionOnMissingBean 這種註解,給客戶以自定義的能力。

// 不加 @Component
public MyFilter implement Filter {
  //...
}

@Configuration
public MyConfig {

  @ConditionOnMissingBean("myFilterBean")
  @Bean
  public MyFilter myFilterBean(){
    return new MyFilter();
  }

  @ConditionOnMissingBean("myFilter")
  @Bean
  public FilterRegistrationBean<MyFilter> myFilter(MyFilter myFilterBean) {
    FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(myFilterBean);
    registration.addUrlPatterns("/*");
    registration.setName("myFilter");
    registration.setOrder(1);
    return registration;
  } 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章