我们在web.xml中配置了一个名称为springSecurityFilterChain的过滤器DelegatingFilterProxy,接下我直接对 DelegatingFilterProxy源码里重要代码进行说明,其中删减掉了一些不重要的代码,大家注意我写的注释就行了!
public class DelegatingFilterProxy extends GenericFilterBean { @Nullable private String contextAttribute; @Nullable private WebApplicationContext webApplicationContext; @Nullable private String targetBeanName; private boolean targetFilterLifecycle; @Nullable private volatile Filter delegate;//注:这个过滤器才是真正加载的过滤器 private final Object delegateMonitor; //注:doFilter才是过滤器的入口,直接从这看! public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { Filter delegateToUse = this.delegate; if (delegateToUse == null) { synchronized(this.delegateMonitor) { delegateToUse = this.delegate; if (delegateToUse == null) { WebApplicationContext wac = this.findWebApplicationContext(); if (wac == null) { throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener or DispatcherServlet registered?"); } //第一步:doFilter中最重要的一步,初始化上面私有过滤器属性delegate delegateToUse = this.initDelegate(wac); } this.delegate = delegateToUse; } } //第三步:执行FilterChainProxy过滤器 this.invokeDelegate(delegateToUse, request, response, filterChain); } //第二步:直接看最终加载的过滤器到底是谁 protected Filter initDelegate(WebApplicationContext wac) throws ServletException { //debug得知targetBeanName为:springSecurityFilterChain String targetBeanName = this.getTargetBeanName(); Assert.state(targetBeanName != null, "No target bean name set"); //debug得知delegate对象为:FilterChainProxy Filter delegate = (Filter)wac.getBean(targetBeanName, Filter.class); if (this.isTargetFilterLifecycle()) { delegate.init(this.getFilterConfig()); } return delegate; } }
第二步debug结果如下:
由此可知,DelegatingFilterProxy通过springSecurityFilterChain这个名称,得到了一个FilterChainProxy过滤器, 最终在第三步执行了这个过滤器。