DelegatingFilterProxy原理解析(shiroFilter)

web.xml 配置

    <!-- 配置shiro过滤器--> 
    <filter>
       <filter-name>shiroFilter</filter-name>
       <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>   
            <param-name>targetFilterLifecycle</param-name>   
            <param-value>true</param-value>   
        </init-param>
    </filter>
    <filter-mapping>
       <filter-name>shiroFilter</filter-name>
       <url-pattern>/*</url-pattern>
       <dispatcher>REQUEST</dispatcher>
       <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

spring bean 配置

    <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        ...
    </bean>

 DelegatingFilterProxy本质是一个Filter类,是怎么和spring中的bean关联起来的

// init方法在父类 GenericFilterBean 中
public class DelegatingFilterProxy extends GenericFilterBean 

1、Filter初始化 

	// org.springframework.web.filter.GenericFilterBean.init(FilterConfig)
	// 去掉一些日志
	public final void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;

		// Set bean properties from init parameters.
		try {
			PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
			initBeanWrapper(bw);
			bw.setPropertyValues(pvs, true);
		}
		catch (BeansException ex) {
			String msg = "Failed to set bean properties on filter '" +
				filterConfig.getFilterName() + "': " + ex.getMessage();
			logger.error(msg, ex);
			throw new NestedServletException(msg, ex);
		}

		// Let subclasses do whatever initialization they like.
		// 交给子类DelegatingFilterProxy实现
		initFilterBean();
	}
	// org.springframework.web.filter.DelegatingFilterProxy.initFilterBean()
	@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) {
					// targetBeanName属性可以通过在web.xml中的filter中的init-param中配置。一般我们不显式的配置
					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上下文
				WebApplicationContext wac = findWebApplicationContext();
				if (wac != null) {
					// 初始化被代理的Filter类(ShiroFilterFactoryBean)
					this.delegate = initDelegate(wac);
				}
			}
		}
	}

	protected final String getFilterName() {
		// 获取web.xml中配置的filter-name值
		// <filter-name>shiroFilter</filter-name>对应<bean id="shiroFilter">
		return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);
	}

	protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
		// 根据targetBeanName从WebApplicationContext上下文中获取bean,并初始化
		Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
		if (isTargetFilterLifecycle()) {
			delegate.init(getFilterConfig());
		}
		return delegate;
	}

2、Filter doFilter

	// org.springframework.web.filter.DelegatingFilterProxy.doFilter(ServletRequest, ServletResponse, FilterChain)
	// 代理类的doFilter方法
	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) {
				if (this.delegate == null) {
					WebApplicationContext wac = findWebApplicationContext();
					if (wac == null) {
						throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
					}
					this.delegate = initDelegate(wac);
				}
				delegateToUse = this.delegate;
			}
		}

		// Let the delegate perform the actual doFilter operation.
		invokeDelegate(delegateToUse, request, response, filterChain);
	}
	
	// 执行被代理类的doFilter方法
	protected void invokeDelegate(
			Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		delegate.doFilter(request, response, filterChain);
	}
发布了53 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/blog_zxb/article/details/100579520