spring-session源码解读-2

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 启用redis sessionspring通过EnableRedisHttpSession注解来启用redid session@Import(RedisHttpSessionConfiguration.class)@Configurationpublic @interface EnableRedisHttpSession { int maxInacti

启用redis session

spring通过EnableRedisHttpSession注解来启用redid session

@Import(RedisHttpSessionConfiguration.class)
@Configuration
public @interface EnableRedisHttpSession {
    int maxInactiveIntervalInSeconds() default 1800;
}

该注解有两个元注解,一个是Configuration, 一个是Import, 上一篇提过Configuration,它就相当于是beans配置,而Import则相当于是beans里嵌套了另一个beans配置项。另外再介绍一下Bean这个注解,这个注解相当于是beans配置里的bean标签,它是注解在方法上的,被注解方法的返回值就是一个spring bean,而相应的方法名就是作为bean name,如果显示的设置了name属性,那就以name属性值作为bean name。

所以可以理解为EnableRedisHttpSession就是一个编程式的配置定义,而RedisHttpSessionConfiguration显然也应该是一个编程式配置定义。

容器对springSessionRepositoryFilter的依赖管理

在RedisHttpSessionConfiguration里很惊喜的发现了第一篇里被注入的“springSessionRepositoryFilter”。

@Bean
    public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository, ServletContext servletContext) {
        SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(sessionRepository);
        sessionRepositoryFilter.setServletContext(servletContext);
        if(httpSessionStrategy != null) {
            sessionRepositoryFilter.setHttpSessionStrategy(httpSessionStrategy);
        }
        return sessionRepositoryFilter;
    }

这里相当于是定义了一个bean-name=”springSessionRepositoryFilter” class=”org.springframework.session.web.http.SessionRepositoryFilter”的bean。

两个参数SessionRepository和ServletContext都是由Spring容器管理的依赖,SessionRepository和SpringSessionRepositoryFilter定义在同一个Configuration里。ServletContext的注入可能会比较令人疑惑,在这个Configuration没有定义它无法定义它,因为它是由Servlet容器生成的。

ContextLoaderListener

在介绍ServletContext的依赖之前,再聊下前文提过的ContextLoaderListener。它由initializer动态注册,其构造函数参数为一个WebApplicationContext,继承于ContextLoader(实际启动WebApplicationContext初始化工作的对象),构造函数参数是一个WebApplicationContext。

Servlet容器启动时会通知ContextLoaderListener,

@Override
    public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
    }

ContextLoaderListener会调用父类ContextLoader的initWebApplicationContext方法来启动ApplicationContext的初始化,

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {

    configureAndRefreshWebApplicationContext(cwac, servletContext);
                              servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

    return this.context;
    }

上面只抽取了ContextLoader的关键逻辑
1. ApplicationContext被默认放入了ServletContext中,key是个默认值。上一篇提过在获取对应name的filter时会从ServletContext里先得ApplicationContext,再获取对应依赖。
2. configureAndRefreshWebApplicationContext这个方法最终启动了ApplictionContext的最核心refresh,这个方法被放在公共抽象类AbstractApplicationContext里,几乎所有的ApplicationContext都会执行。这个阶段结束后,ApplicationContext也就启动完毕,整个容器的依赖也就完成。因为篇幅太长ApplicationContext启动的细节就不再展开。

ServletContext的依赖

在容器refresh阶段会通过postProcessBeanFactory这个策略方法对容器对应的BeanFactory做后处理,一般是设置一些beanPostProcessor之类,对于WebApplicationContext则会处理ServletContext的依赖。

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

//在这里将ServletContext    作为一个bean管理起来WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
    }

至此,springSessionRepositoryFilter的依赖也注入完毕。综合1,2两篇基本上就了解了filter是如何被spring容器管理并如何通过代理动态注册给容器的。那么这个拦截器究竟能做什么?这就留到后面专门通过一篇文章来展开

《spring-session源码解读1》

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
2月前
|
监控 数据可视化 关系型数据库
微服务架构+Java+Spring Cloud +UniApp +MySql智慧工地系统源码
项目管理:项目名称、施工单位名称、项目地址、项目地址、总造价、总面积、施工准可证、开工日期、计划竣工日期、项目状态等。
304 6
|
2月前
Spring5源码(45)-@Transactional声明式事物(三)事物创建
Spring5源码(45)-@Transactional声明式事物(三)事物创建
39 0
|
2月前
|
Java Spring
Spring5源码(43)-@Transactional声明式事物(一)事物管理步骤简析
Spring5源码(43)-@Transactional声明式事物(一)事物管理步骤简析
33 0
|
2月前
|
Java 关系型数据库 数据库连接
Spring源码解析--深入Spring事务原理
本文将带领大家领略Spring事务的风采,Spring事务是我们在日常开发中经常会遇到的,也是各种大小面试中的高频题,希望通过本文,能让大家对Spring事务有个深入的了解,无论开发还是面试,都不会让Spring事务成为拦路虎。
34 1
|
2月前
|
Java 应用服务中间件 Spring
Spring5源码(50)-SpringMVC源码阅读环境搭建
Spring5源码(50)-SpringMVC源码阅读环境搭建
40 0
|
1月前
|
Java 测试技术 数据库连接
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
|
29天前
|
Java Spring
使用spring实现邮件的发送(含测试,源码,注释)
使用spring实现邮件的发送(含测试,源码,注释)
7 0
|
1月前
|
Java Spring 容器
【Spring源码】单例创建期间进行同步可能会导致死锁?
通过这个标题我们就可以思考本次的阅读线索了,看起来可以学到不少东西。1. 旧代码的死锁是怎么产生的。2. 贡献者通过改变什么来解决本次PR的问题呢?而阅读线索2的答案也显而易见,就是上文提到的通过后台线程来创建Micrometer单例...
40 3
|
1月前
|
XML Java 开发者
【Spring源码解读 底层原理高级进阶】【上】探寻Spring内部:BeanFactory和ApplicationContext实现原理讲解
【Spring源码解读 底层原理高级进阶】【上】探寻Spring内部:BeanFactory和ApplicationContext实现原理讲解