Spring Security启动加载流程梳理
注:本文使用的Spring版本:4.0.2.RELEASE ,Spring Security版本:3.2.8.RELEASE
- web.xml配置
使用Spring Security需要在web.xml加入一个Filter,如下:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
查看DelegatingFilterProxy源码发现这个类是位于spring-web包下:
网上对这个类的描述也比较多,大致如下:
说明这个类本身是和springSecurity无关。DelegatingFilterProxy类继承于抽象类GenericFilterBean,间接地实现了javax.servlet.Filter接口,Servlet容器在启动时,首先会调用Filter的init方法, GenericFilterBean的作用主要是可以把Filter的初始化参数自动地set到继承于GenericFilterBean类的Filter中去。
先来看下这个类的继承关系:
继承关系确实是继承了GenericFilterBean并且实现了Filter接口
然后看下它的初始化的方法。既然看到继承了Filter类,那么初始化肯定是从init()方法开始的,我们来找下init(),
发现类DelegatingFilterProxy中没有init方法,然后看下其父类GenericFilterBean结构:
找到了init()方法,然后来看下方法内容:
发现其调用了initFilterBean()方法,刚才在DelegatingFilterProxy类中我们也看到有initFilterBean()方法,来看下DelegatingFilterProxy中的initFilterBean()方法:
中间看到有个targetBeanName,我们没有定义,此处使用的是Filter的名字springSecurityFilterChain,后面其调用了initDelegate方法,我们来看下initDelegate方法:
initDelegate方法中,我们看到使用getBean获取到了一个Filter,bean的名称使用的是属性targetBeanName此处为springSecurityFilterChain,跟踪代码我们发现此处获取到的Filter为org.springframework.security.filterChainProxy,截图如下:
看到这个好多人都会有疑问,明明使用的bean名称是springSecurityFilterChain,为什么获取到filterChainProxy呢,我们接着跟踪源码,此处源码较多使用多个图拼接展示:
图中最后SimpleAliasRegistry类的canonicalName方法中通过循环将springSecurityFilterChain转换为filterChainProxy,其中aliasMap的初始化赋值则是在SimpleAliasRegistry类的registerAlias方法:
然后在HttpSecurityBeanDefinitionParser类中的registerFilterChainProxyIfNecessary方法中找到了对springSecurityFilterChain的赋值:
HttpSecurityBeanDefinitionParser类是spring Security的一种解析器,其主要作用是实例化org.springframework.security.web.FilterChainProxy,此处不多做介绍(看到有篇文章介绍对HttpSecurityBeanDefinitionParser类做了介绍,想了解的可以参考下:HttpSecurityBeanDefinitionParser浅析)。
至此就明白了Spring Security使用springSecurityFilterChain获取到的Filter为org.springframework.security.filterChainProxy的原理。并且Filter的init()方法也在执行完initFilterBean()后结束,至于spring Security中xml配置文件中标签的加载,可以参考下Spring的自定义标签的解析方法,有人做了分析:浅谈Spring的BeanDefinitionParser的触发流程,但是这篇文章没介绍Spring的加载过程,想了解的可以参考这个:Spring启动执行流程梳理。