1. 程式人生 > >Spring Web學習--DelegatingFilterProxy 代理Filter

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。

1、DelegatingFilterProxy根據targetBeanName從Spring 容器中獲取被注入到Spring 容器的Filter實現類,在DelegatingFilterProxy配置時一般需要配置屬性targetBeanName

@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;
	}

2、在DelegatingFilterProxy的實現方法doFilter中,其實最終呼叫的是委派的類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);
	}

總結:Spring web通過提高DelegatingProxyFilter類給開發者提供了便利