[转]springSecurity源码分析—DelegatingFilterProxy类的作用
使用过springSecurity的朋友都知道,首先需要在web.xml进行以下配置,
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value> <!-- 默认是false -->
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
从这个配置中,可能会给我们造成一个错觉,以为DelegatingFilterProxy类就是springSecurity的入口,但其实这个类位于spring-web-3.0.5.RELEASE.jar这个jar下面,说明这个类本身是和springSecurity无关。DelegatingFilterProxy类继承于抽象类GenericFilterBean,间接地implement 了javax.servlet.Filter接口,Servlet容器在启动时,首先会调用Filter的init方法,GenericFilterBean的作用主要是可以把Filter的初始化参数自动地set到继承于GenericFilterBean类的Filter中去。在其init方法的如下代码就是做了这个事:
|
1
2
3
4
5
6
|
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));initBeanWrapper(bw);bw.setPropertyValues(pvs, true); |
另外在init方法中调用了initFilterBean()方法,该方法是GenericFilterBean类是特地留给子类扩展用的,
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
protected void initFilterBean() throws ServletException { // 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. synchronized (this.delegateMonitor) { WebApplicationContext wac = findWebApplicationContext(); if (wac != null) { this.delegate = initDelegate(wac); } } } |
可以看出上述代码首先看Filter是否提供了targetBeanName初始化参数,如果没有提供则直接使用filter的name做为beanName,产生了beanName后,由于我们在web.xml的filter的name是springSecurityFilterChain,从spring的IOC容器中取出bean的代码是initDelegate方法,下面是该方法代码:
|
1
2
3
4
5
6
7
|
protected Filter initDelegate(WebApplicationContext wac) throws ServletException { Filter delegate = wac.getBean(getTargetBeanName(), Filter.class); if (isTargetFilterLifecycle()) { delegate.init(getFilterConfig()); } return delegate;} |
通过跟踪代码,发现取出的bean是org.springframework.security.FilterChainProxy,该类也是继承于GenericFilterBean,取出bean后,判断targetFilterLifecycle属性是false还是true,决定是否调用该类的init方法。这个FilterChainProxy bean实例最终被保存在DelegatingFilterProxy类的delegate属性里,
下面看一下DelegatingFilterProxy类的doFilter方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { // Lazily initialize the delegate if necessary. Filter 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); } |
真正要关注invokeDelegate(delegateToUse, request, response, filterChain);这句代码,在下面可以看出DelegatingFilterProxy类实际是用其delegate属性即org.springframework.security.FilterChainProxy实例的doFilter方法来响应请求。
|
1
2
3
4
5
6
|
protected void invokeDelegate( Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { delegate.doFilter(request, response, filterChain); } |
以上就是DelegatingFilterProxy类的一些内部运行机制,其实主要作用就是一个代理模式的应用,可以把servlet 容器中的filter同spring容器中的bean关联起来。
此外还要注意一个DelegatingFilterProxy的一个初始化参数:targetFilterLifecycle ,其默认值为false 。 但如果被其代理的filter的init()方法和destry()方法需要被调用时,需要设置targetFilterLifecycle为true。具体可见DelegatingFilterProxy中的如下代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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); } } } }protected Filter initDelegate(WebApplicationContext wac) throws ServletException { Filter delegate = wac.getBean(getTargetBeanName(), Filter.class); if (isTargetFilterLifecycle()) { //注意这行 delegate.init(getFilterConfig()); } return delegate; } |
[转]springSecurity源码分析—DelegatingFilterProxy类的作用的更多相关文章
- Struts2 源码分析——DefaultActionInvocation类的执行action
本章简言 上一章讲到关于拦截器的机制的知识点,让我们对拦截器有了一定的认识.我们也清楚的知道在执行用户action类实例之前,struts2会先去执行当前action类对应的拦截器.而关于在哪里执行a ...
- Struts2 源码分析——Result类实例
本章简言 上一章笔者讲到关于DefaultActionInvocation类执行action的相关知识.我们清楚的知道在执行action类实例之后会相关处理返回的结果.而这章笔者将对处理结果相关的内容 ...
- tornado框架源码分析---Application类之debug参数
先贴上Application这个类的源码. class Application(httputil.HTTPServerConnectionDelegate): """A ...
- LinqToDB 源码分析——DataContext类
LinqToDB框架是一个轻量级的ORM框架.当然,功能上来讲一定比不上Entity Framework的强大.但是在使用上总让笔者感觉有一点Entity Framework的影子.笔者想过可能的原因 ...
- Threadlocal源码分析以及其中WeakReference作用分析
今天在看Spring 3.x企业应用开发实战,第九章 Spring的事务管理,9.2.2节ThreadLocal的接口方法时,书上有提到Threadlocal的简单实现,我就去看了下JDK1.8的Th ...
- yii2 源码分析 object类分析 (一)
转载请注明链接http://www.cnblogs.com/liuwanqiu/p/6737327.html yii2基本上所有的类都是继承的object类,下面就来分析一下object类吧 obje ...
- yii2 源码分析Action类分析 (六)
Action类是控制器的基类, <?php namespace yii\base; use Yii; /** * Action是所有控制器动作类的基类,它继承组件类 * * 动作提供了重用动作方 ...
- yii2 源码分析 model类分析 (五)
模型类是数据模型的基类.此类继承了组件类,实现了3个接口 先介绍一下模型类前面的大量注释说了什么: * 模型类是数据模型的基类.此类继承了组件类,实现了3个接口 * 实现了IteratorAggreg ...
- yii2 源码分析Behavior类分析 (四)
Behavior类是所有事件类的基类,它继承自object类 Behavior类的前面注释描述大概意思: * Behavior类是所有事件类的基类 * * 一个行为可以用来增强现有组件的功能,而不需要 ...
随机推荐
- VS2015 之 常用快捷键
调试执行 F5,终止调试执行 Shift+F5 启动执行 Ctrl+F5 查找下一个 F3,查找上一个 Shift+F3 附加到进程 Ctrl+Alt+P,逐过程 F10,逐语句执行 F11 切换断点 ...
- bootstrap——强大的网页设计元素模板
本文介绍一个网页设计工具——bootstrap,它包含了很多华丽的按钮及排版,我们可以在网页设计中直接使用它,尤其是加入我们只是想简单的使用一下的话,将会是一个不错的选择,下面是几张examples, ...
- 微信小程序 - 怎样合理设计小程序
假如我们无意中,把腾讯地图或者高德地图的管理Key删了! 关于定位的一切相关模块就都会报废! 接着呢?客户会找你,对你公司信任感下降,一系列问题接踵而来 最好的办法就是先预留key后台管理 “随时可以 ...
- Customize Web Sessions List
To customize Fiddler's Web Sessions List, add rules using FiddlerScript to the OnBeforeRequest funct ...
- Git 推送和删除远程标签
事实上Git 的推送和删除远程标签命令是相同的,删除操作实际上就是推送空的源标签refs: git push origin 标签名 相当于 git push origin refs/tags/源标签名 ...
- Java通过Fork/Join来优化并行计算
Java代码: package Threads; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Recur ...
- V-rep学习笔记:ROSInterface
Ubuntu 14.04 上安装V-rep 3.4.0 进入VREP官网下载Linux版本的V-rep(注意V-rep 3.4.0只有64位的版本,因此操作系统也要与之对应,Ubuntu 32位系统就 ...
- python模块之imghdr(识别不同格式的图片文件)
# -*- coding: utf-8 -*- #python 27 #xiaodeng #python模块之imghdr(识别不同格式的图片文件) import imghdr '''>> ...
- [Dubbo实战]dubbo + zookeeper + spring 实战 (转)
这里最熟悉的就是spring了,项目中应用很多.dubbo是一个实现分布式的框架,zookeeper是注册中心.给我的感觉就像多对多关系的两者表,zookeeper相当于第三张表维护关系.下面通过一个 ...
- ios中xml和html解析(封装)
下载地址 http://pan.baidu.com/share/link?shareid=2902188921&uk=923776187 GDataXML和TFHpple配置是一样的(配置方 ...