内容简介:本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;本系列开始,将讲解有关 Spring Security 的配置相关的内容;本文为作者的原创作品,转载需注明出处;
本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;
本系列开始,将讲解有关 Spring Security 的配置相关的内容;
本文为作者的原创作品,转载需注明出处;
简介
由前面的文章分析可知 DelegatingFilterProxy 是Web Servlet Filters 中的一个 Filter;该 Filter 代理了FilterChainProxy;FilterChainProxy 又包含了多个SecurityFilterChain 对象;由此,整个 Spring Security 的过滤链的机制由此就建立起来了;但是问题来了,DelegatingFilterProxy 本身作为 Filter 是如何注册到 Spring Web 容器中的呢?本文,笔者将会带领读者们来回答这个问题;
笔者使用的环境是 Spring Boot,该加载的方式与 Spring MVC 的方式有很大的异同;Spring MVC 的加载方式可以参考 http://www.tianshouzhi.com/api/tutorials/spring_security_4/262 章节“ 过滤器注册过程的源码分析 ”部分,该部分详细的介绍了如何通过 ServletContainerInitializer 来初始化并加载过滤器 Filters;
DelegatingFilterProxy 载入流程分析
DelegatingFilterProxyRegistrationBean
本小节将记录笔者为了搞清楚在 Spring Boot 环境下 DelegatingFilterProxy 是如何作为 Filter 加载入 Spring Web 容器中的;
首先,将断点打在 DelegatingFilterProxy(String targetBeanName, WebApplicationContext wac) 中,我们将会得到如下的调试状态,
如图所示,Spring Boot 使用的是 TomcatEmbeddedContext 的方式来加载的 Filters,所以和 Spring MVC 通过使用 AbstractSecurityWebApplicationInitializer 来加载 Filter 的方式不同,下面我们就这种方式来进行分析,看看是如何通过 TomcatEmbeddedContext 一步一步的来加载 Filters 的?
然后,看 AnnotationConfigEmbeddedWebApplicationContext.setInitialize(ServletContext) 方法
答案就在 getServletContextInitializerBeans() 方法中,该方法返回如下对象列表;
是的,我发现了什么,似曾相似,这不就是前文提到的6 大 Filters;而 DelegatingFilterProxyRegistrationBean
所代表的正是 DelegatingFilterProxy
;下面深入 getServletContextInitializerBeans() 方法,
上面的代码非常的关键了,通过传入 BeanFactory 作为构造参数来初始化构造 ServletContextInitializerBeans 的来获得这 6 大 Filters; 这里需要注意的一个细节是,ServletContextInitializerBeans 本身是一个 Collection 类型;
-
addServletContextInitializerBeans(ListableBeanFactory beanFactory)
可见构造函数中首先通过 addServletContextInitializerBeans(ListableBeanFactory beanFactory),然后通过在 Spring 容器中通过获取类型为 ServletContextInitializer 的 Spring Beans,
DelegatingFilterProxyRegistrationBean
和其余 5 大 Filters 均实现了该接口;所以,DelegatingFilterProxyRegistrationBean 以及其余 Filters 将会在这里被取出; -
addServletContextInitializerBean(String beanName, ServletContextInitializer initializer, ListableBeanFactory beanFactory)
该方法将对应的 Filter 加入 initializers 中,既是将 Filter 注入到 Spring Web 容器中;
从上述的第 #1 点可以知道,通过从容器中查找类型为 ServletContextInitializer 的 bean,既可以找到 DelegatingFilterProxyRegistrationBean 和其余 5 大 Filters;那么问题是,这些 Filters 是如何提前被注入到 Spring 容器中的呢?
RegistrationBean
本小节将回答上一小节末尾所提到的问题,那就是 DelegatingFilterProxyRegistrationBean
是如何作为 Filter 注入到 Spring 容器中的?其实,它的答案正是 org.springframework.boot.context.embedded.RegistrationBean 所涉及到的逻辑,该部分逻辑也正是 Spring Boot 的专属逻辑;下面,笔者将简要介绍一下 DelegatingFilterProxyRegistrationBean
做为 Filter 被注入到 Spring 容器中的逻辑,看一下 org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration 类的逻辑
通过 SecurityFilterAutoConfiguration 自动的将 DelegatingFilterProxyRegistrationBean
注入到 Spring Web 容器中;Spring Boot 放弃了以往类似 Spring MVC 加载 Filter 繁琐的方式,直接通过 RegisterBean 的方式来注册 ServletContext 中所需要的资源;这里不打算细说有关 RegistrationBean 的相关的逻辑,将来打算将这部分内容在 Spring Boot 的相关章节中做进一步描述;
Reference: http://www.tianshouzhi.com/api/tutorials/springboot/89
FilterChainProxy 作为代理载入 DelegatingFilterProxy 的流程
这里不打算做深入的分析了,下面描述了该载入流程的入口方法,
DelegatingFilterProxy.class
/** * Initialize the Filter delegate, defined as bean the given Spring * application context. * <p>The default implementation fetches the bean from the application context * and calls the standard {@code Filter.init} method on it, passing * in the FilterConfig of this Filter proxy. * @param wac the root application context * @return the initialized delegate Filter * @throws ServletException if thrown by the Filter * @see #getTargetBeanName() * @see #isTargetFilterLifecycle() * @see #getFilterConfig() * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ protected Filter initDelegate(WebApplicationContext wac) throws ServletException { Filter delegate = wac.getBean(getTargetBeanName(), Filter.class); if (isTargetFilterLifecycle()) { delegate.init(getFilterConfig()); } return delegate; }
核心逻辑在上述代码的第 16 行;target name 既是 “springSecurityFilterChain”,而该 bean name 对应的正好是 FilterChainProxy Spring Bean;
以上所述就是小编给大家介绍的《Spring Security 源码分析九:Java config - 加载 DelegatingFilterProxy》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- springMVC容器加载源码分析
- Java类加载源码阅读
- caffe源码阅读(1): 数据加载
- Glide 图片加载框架源码解析
- Tinker源码分析(二):加载补丁
- 【MyBatis源码分析】Configuration加载(下篇)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。