为什么80%的码农都做不了架构师?>>>   

在FilterChainProxy初始化的过程中,大概描述了标签解析的一些步骤,但不够详细
  <http auto-config="true">
    <remember-me key="workweb" token-validity-seconds="3600" data-source-ref="dataSource"/>
    <form-login login-page="/login.jsp"/>
    <logout logout-success-url="/login.jsp"/>
    <intercept-url pattern="/*" access="ROLE_USER"/>
  </http>

http标签的解析过程由类org.springframework.security.config.http.HttpSecurityBeanDefinitionParser解析。
public BeanDefinition parse(Element element, ParserContext pc) {
        CompositeComponentDefinition compositeDef =
            new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
        pc.pushContainingComponent(compositeDef);
        final Object source = pc.extractSource(element);
        //portMapperName、matcher主要提供给SSL相关类使用
        final String portMapperName = createPortMapper(element, pc);
        final UrlMatcher matcher = createUrlMatcher(element);
        //http标签构造器,该构造函数中对intercept-url、create-session子标签
         //进行了预处理,并将所有的intercept-url信息放到List中。
        HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc, matcher, portMapperName);
        //处理List中的intercept-url信息(如pattern、filters),并将结果放到
         //Map集合filterChainMap中
        httpBldr.parseInterceptUrlsForEmptyFilterChains();
        //创建过滤器SecurityContextPersistenceFilter
        httpBldr.createSecurityContextPersistenceFilter();
        //创建过滤器SessionManagementFilter
        httpBldr.createSessionManagementFilters();
        //新建一个空的provider集合
        ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
        //通过空的provider集合产生一个ProviderManager的bean定义
        BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders, null);
        //创建过滤器SecurityContextHolderAwareRequestFilter
        httpBldr.createServletApiFilter();
        //判断intercept-url标签是否有requires-channel属性,如果有,则创建过滤器
         //ChannelProcessingFilter
        httpBldr.createChannelProcessingFilter();
        //创建过滤器FilterSecurityInterceptor
        //这个创建过程比较复杂,分别为:
         //1.需要判断是否使用表达式use-expressions
        //2.解析intercept-url中的access等属性
         //3.RoleVoter、AffirmativeBased的定义…………
        httpBldr.createFilterSecurityInterceptor(authenticationManager);
        //下面是与认证有关的过滤器,HttpConfigurationBuilder,
         //AuthenticationConfigBuilder将解析的职责进行了分离
        AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
                httpBldr.isAllowSessionCreation(), portMapperName);
        //创建过滤器AnonymousAuthenticationFilter,并且构造了provider:
         //AnonymousAuthenticationProvider,供ProviderManager使用
        authBldr.createAnonymousFilter();
        //判断是否有remember-me标签,如果有,则创建过滤器
         //RememberMeAuthenticationFilter,并且构造了provider:
         //RememberMeAuthenticationProvider供ProviderManager使用
        authBldr.createRememberMeFilter(authenticationManager);
        //判断是否有request-cache标签,如果有,则构造ref指明的bean定义
         //如果没有,则构造HttpSessionRequestCache缓存
        authBldr.createRequestCache();
        //创建过滤器BasicAuthenticationFilter
        authBldr.createBasicFilter(authenticationManager);
        //创建LoginUrlAuthenticationEntryPoint,以及创建过滤器
         //UsernamePasswordAuthenticationFilter
        authBldr.createFormLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
        //判断是否使用了openid-login,如果有,则构造openId客户端
         //org.springframework.security.openid.OpenID4JavaConsumer
        authBldr.createOpenIDLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
        //判断是否使用了x509,如果有,则创建过滤器
         //X509AuthenticationFilter
        authBldr.createX509Filter(authenticationManager);
        //判断是否配置了logout,如果有,则创建过滤器LogoutFilter
        authBldr.createLogoutFilter();
        //判断是否配置login-page属性,如果没有,则创建过滤器
         //DefaultLoginPageGeneratingFilter,生成默认登录页面
        authBldr.createLoginPageFilterIfNeeded();
        //创建UserDetailsServiceInjectionBeanPostProcessor
        //动态向x509、openID、rememberme服务注入UserDetailsService
         //主要使用了spring的BeanPostProcessor接口功能
        authBldr.createUserServiceInjector();
        //创建过滤器ExceptionTranslationFilter
        authBldr.createExceptionTranslationFilter();

List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();
        //向FilterChain链中添加filters
        unorderedFilterChain.addAll(httpBldr.getFilters());
        unorderedFilterChain.addAll(authBldr.getFilters());
        //向ProviderManager中添加provider
        authenticationProviders.addAll(authBldr.getProviders());

BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);
        requestCacheAwareFilter.getPropertyValues().addPropertyValue("requestCache", authBldr.getRequestCache());
        unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));
        //添加自定义的Filter,也就是custom-filter标签定义的Filter
        unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
        //对FilterChian链中的Filter进行排序,排序规则参见SecurityFilters枚举类
        Collections.sort(unorderedFilterChain, new OrderComparator());
        checkFilterChainOrder(unorderedFilterChain, pc, source);

List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();

for (OrderDecorator od : unorderedFilterChain) {
            filterChain.add(od.bean);
        }

ManagedMap<BeanDefinition, List<BeanMetadataElement>> filterChainMap = httpBldr.getFilterChainMap();
        BeanDefinition universalMatch = new RootBeanDefinition(String.class);
        universalMatch.getConstructorArgumentValues().addGenericArgumentValue(matcher.getUniversalMatchPattern());
        filterChainMap.put(universalMatch, filterChain);
        //构造FilterChainProxy的Bean
        registerFilterChainProxy(pc, filterChainMap, matcher, source);

pc.popAndRegisterContainingComponent();
        return null;
    }

至此,大概http标签的解析已经差不多了,虽然每个Filter的BeanDefinition创建过程还没有一一细说,但基本步骤如下:

1.通过Filter的类路径获取BeanDefinitionBuilder对象,如
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName);

2.解析xml标签属性,再通过BeanDefinitionBuilder的addPropertyValue、addPropertyReference等方法设置Filter对应BeanDefinition的属性值、依赖bean

3.注册BeanDefinition。通过
ParserContext.registerBeanComponent(
new BeanComponentDefinition(BeanDefinition,beanId));
完成bean的注册。还可以通过ParserContext.getRegistry().registerAlias
方法注册bean的别名

实际上,标签解析就是构造BeanDefinition,然后注册到bean factory中。而BeanDefinition就是Spring中定义bean的数据结构。

转载于:https://my.oschina.net/blooms/blog/79106

Spring Security3源码分析-http标签解析(转)相关推荐

  1. Spring Security3源码分析-UsernamePasswordAuthenticationFilter分析

    2019独角兽企业重金招聘Python工程师标准>>> UsernamePasswordAuthenticationFilter过滤器对应的类路径为 org.springframew ...

  2. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  3. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  4. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  5. spring AOP源码分析(一)

    spring AOP源码分析(一) 对于springAOP的源码分析,我打算分三部分来讲解:1.配置文件的解析,解析为BeanDefination和其他信息然后注册到BeanFactory中:2.为目 ...

  6. 源码分析 merge 标签减少布局层级的秘密(Android Q)

    源码分析 merge 标签减少布局层级的秘密(Android Q) 我在<Android 渲染性能优化--你需要知道的一切!>一文中介绍过,merge 标签用于减少 View 树的层次来优 ...

  7. 【Spring】Spring AOP源码分析-导读(一)

    文章目录 1.简介 2.AOP 原理 3.AOP 术语及相应的实现 3.1 连接点 - Joinpoint 3.2 切点 - Pointcut 3.3 通知 - Advice 3.4 切面 - Asp ...

  8. 视频教程-Spring底层源码分析-Java

    Spring底层源码分析 鲁班学院-子路老师曾就职于谷歌.天猫电商等多家互联网公司,历任java架构师.研发经理等职位,参与并主导千万级并发电商网站与后端供应链研发体系搭建,多次参与电商大促活动技术保 ...

  9. 【转】Spring AMQP 源码分析 01 - Impatient

    转自首夜盲毒预言家的文章 Spring AMQP 源码分析 01 - Impatient ### 准备 ## 目标 了解 Spring AMQP 核心代码 ## 前置知识 RabbitMQ 入门 ## ...

最新文章

  1. torch.empty()
  2. Java Persistence API中的FetchType LAZY和EAGER之间的区别?
  3. 如何设置网站标题更有利于网站SEO优化?
  4. pl/sql 报ORA-12154: TNS:无法解析指定的连接标志符
  5. android object比较大小
  6. centos7创建asm磁盘_Oracle ASM 磁盘组基础知识整理(收藏版)
  7. docker 删除所有镜像_Docker常用命令
  8. 如何解决SVN 清理失败
  9. 恒大紧急辟谣“资金链断裂”,股价止跌回升
  10. 视图之一--创建简单的视图
  11. wpf 如何实现窗口浮动_如何实现工作表数据与UserForm窗口的交互,显示第一条记录...
  12. 这家初创公司用端到端安全保护物联网设备
  13. python 和vba在财务上_Excel函数和VBA技术在财务工作中的应用
  14. PMP备考经验分享 制表很重要
  15. pyinstaller打包py文件为单个文件或多个文件
  16. 三菱FX系列PLC编程口通讯协议详解
  17. 2021-02-07 - GraphQL - 学习/实践
  18. 华为WEB前端全栈成长计划招募
  19. bp神经网络实现人脸识别,卷积神经网络手势识别
  20. 2022 QS世界大学排名发布!MIT霸榜,清北冲上全球前20

热门文章

  1. Android SlidingMenu插件的使用
  2. metaWeblog 相关的参数
  3. css网页布局兼容性有哪些要点与诀窍
  4. Ubuntu时间显示不准确的解决方案
  5. c语言基础回顾 —— 其他知识点
  6. pwd命令是什么的缩写_手机学编程(2)目录管理命令
  7. 信息系统管理十大知识领域
  8. Mac中Finder是什么?怎么打开?
  9. ef core mysql 生成迁移失败_EFCore + MySql codeFirst 迁移 Migration出现的问题
  10. 电脑技巧:Windows服务器挂载磁盘方法介绍