天天看點

Spring Web學習--DelegatingFilterProxy 代理Filter

       Spring web在設計的時候考慮到某些功能的實作是通過Filter來攔截進行實作的,如果直接的簡單的實作幾個Filter好像也不是不可以(平時我們就是這麼用的),但是Spring架構最核心的是IOC容器,和Spring架構最好的實作就是将要實作的Filter功能注冊到IOC容器的一個Bean,這樣就可以和Spring IOC容器進行完美的融合,是以Spring Web設計了DelegatingFilterProxy。本質上來說DelegatingFilterProxy就是一個Filter,其間接實作了Filter接口,但是在doFilter中其實調用的從Spring 容器中擷取到的代理Filter的實作類delegate。

@Override
protected void initFilterBean() throws ServletException {
  synchronized (this.delegateMonitor) {
    if (this.delegate == null) {
      // If no target bean name specified, use filter name.
                        //當Filter配置時如果沒有設定targentBeanName屬性,則直接根據Filter名稱來查找
      if (this.targetBeanName == null) {
        this.targetBeanName = getFilterName();
      }
      // Fetch Spring root application context and initialize the delegate early,
      // if possible. If the root application context will be started after this
      // filter proxy, we'll have to resort to lazy initialization.
      WebApplicationContext wac = findWebApplicationContext();
      if (wac != null) {
                                //從Spring容器中擷取注入的Filter的實作類
        this.delegate = initDelegate(wac);
      }
    }
  }
}

protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
    //從Spring 容器中擷取注入的Filter的實作類
    Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
    if (isTargetFilterLifecycle()) {
      delegate.init(getFilterConfig());
    }
    return delegate;
  }      
@Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {

    // Lazily initialize the delegate if necessary.
    //擷取委派Filter實作類
    Filter delegateToUse = this.delegate;
    if (delegateToUse == null) {
      synchronized (this.delegateMonitor) {
        if (this.delegate == null) {
          WebApplicationContext wac = findWebApplicationContext();
          if (wac == null) {
            throw new IllegalStateException("No WebApplicationContext found: " +
                "no ContextLoaderListener or DispatcherServlet registered?");
          }
          this.delegate = initDelegate(wac);
        }
        delegateToUse = this.delegate;
      }
    }

    // Let the delegate perform the actual doFilter operation.
    invokeDelegate(delegateToUse, request, response, filterChain);
  }
  
  //調用委派的Filter的doFilter方法
  protected void invokeDelegate(
      Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {

    delegate.doFilter(request, response, filterChain);
  }