DelegatingFilterProxy of spring framework

Note: the analysis version is spring framework-4.3. X, and the source code can be downloaded on Github

1. Class inheritance diagram

Previous picture

Figure 1 class inheritance diagram of DelegatingFilterProxy

DelegatingFilterProxy just inherits GenericFilterBean directly, as follows

    List-1

public class DelegatingFilterProxy extends GenericFilterBean {

2. Explanation of important methods

DelegatingFilterProxy overrides the following methods in the parent class

    List-2

	@Override
	protected void initFilterBean() throws ServletException {
		synchronized (this.delegateMonitor) {
			if (this.delegate == null) {
				// If no target bean name specified, use filter name.
				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) {
					this.delegate = initDelegate(wac);
				}
			}
		}
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

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

		// Let the delegate perform the actual doFilter operation.
		invokeDelegate(delegateToUse, request, response, filterChain);
	}

	@Override
	public void destroy() {
		Filter delegateToUse = this.delegate;
		if (delegateToUse != null) {
			destroyDelegate(delegateToUse);
		}
	}

Using Template pattern pattern, the attribute targetBeanName in DelegatingFilterProxy is the name of a bean, and the bean should implement Filter. Spring will automatically retrieve the bean corresponding to the targetBeanName from the web application, and then use the bean

 

Because DelegatingFilterProxy indirectly implements Filter, the doFilter method should be implemented as follows:

    List-3

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

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

		// Let the delegate perform the actual doFilter operation.
		invokeDelegate(delegateToUse, request, response, filterChain);
	}

	/**
	 * Actually invoke the delegate Filter with the given request and response.
	 * @param delegate the delegate Filter
	 * @param request the current HTTP request
	 * @param response the current HTTP response
	 * @param filterChain the current FilterChain
	 * @throws ServletException if thrown by the Filter
	 * @throws IOException if thrown by the Filter
	 */
	protected void invokeDelegate(
			Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

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

The invokeDelegate method is invoked in doFilter, and the doFilter method of delegate is invoked in invokeDelegate.

The call sequence diagram is as follows:

 

Figure 2 doFilter call sequence diagram of DelegatingFilterProxy

 

Reflection:

1. There are attributes in DelegatingFilterProxy, as shown in List-4 below. why can DelegatingFilterProxy get the bean corresponding to targetBeanName from the web container even if the value of the specified webApplicationContext is not displayed? This is because DelegatingFilterProxy implements Filter, and there is a method init in the Filter interface, as shown in List-5 below. There is a method getServletContext, getServletContext in the parameter FilterConfig of init method The next method returns a ServletContext. The ServletContext has a getAttribute method. This method can get the value bound to the ServletContext. If you know what ContextLoadListener and dispatcher servlet implement, you should understand.

    List-4

	private WebApplicationContext webApplicationContext;

    List-5

    public void init(FilterConfig filterConfig) throws ServletException;

    List-6

    public ServletContext getServletContext();

Keywords: Spring github Attribute

Added by Elizabeth on Fri, 03 Jan 2020 14:38:56 +0200