1. org.apache.catalina.session.StandardSession 这是servlet-api jar包中的一个类。是session接口的标准实现。当session创建的时候会通知监听者,同理,session销毁的时候也会产生事件,代码如下:

  1. /**
  2. * Inform the listeners about the new session.
  3. *
  4. */
  5. public void tellNew() {
  6.  
  7. // Notify interested session event listeners
  8. fireSessionEvent(Session.SESSION_CREATED_EVENT, null);
  9.  
  10. // Notify interested application event listeners
  11. Context context = (Context) manager.getContainer();
  12. Object listeners[] = context.getApplicationLifecycleListeners();
  13. if (listeners != null) {
  14. HttpSessionEvent event =
  15. new HttpSessionEvent(getSession());
  16. for (int i = 0; i < listeners.length; i++) {
  17. if (!(listeners[i] instanceof HttpSessionListener))
  18. continue;
  19. HttpSessionListener listener =
  20. (HttpSessionListener) listeners[i];
  21. try {
  22. context.fireContainerEvent("beforeSessionCreated",
  23. listener);
  24. listener.sessionCreated(event);
  25. context.fireContainerEvent("afterSessionCreated", listener);
  26. } catch (Throwable t) {
  27. ExceptionUtils.handleThrowable(t);
  28. try {
  29. context.fireContainerEvent("afterSessionCreated",
  30. listener);
  31. } catch (Exception e) {
  32. // Ignore
  33. }
  34. manager.getContainer().getLogger().error
  35. (sm.getString("standardSession.sessionEvent"), t);
  36. }
  37. }
  38. }
  39.  
  40. }

  

2. 上面标红的session event监听器哪里来的呢?答案是web.xml。我们需要在web.xml中添加如下配置:

  1. <listener>
  2. <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
  3. </listener>

3. 接着,在HttpSessionEventPublisher中,从HttpSessionEvent中获取session,再从session中获取ServletContext,进而获取spring 容器(ApplicationContext),然后往容器发送event,代码如下:

  1. /**
  2. * Handles the HttpSessionEvent by publishing a {@link HttpSessionCreatedEvent} to the
  3. * application appContext.
  4. *
  5. * @param event HttpSessionEvent passed in by the container
  6. */
  7. public void sessionCreated(HttpSessionEvent event) {
  8. HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(event.getSession());
  9. Log log = LogFactory.getLog(LOGGER_NAME);
  10.  
  11. if (log.isDebugEnabled()) {
  12. log.debug("Publishing event: " + e);
  13. }
  14.  
  15. getContext(event.getSession().getServletContext()).publishEvent(e);
  16. }

 

AbstractApplicationContext.java: 事件发布

 

  1. protected void publishEvent(Object event, ResolvableType eventType) {
  2. Assert.notNull(event, "Event must not be null");
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Publishing event in " + getDisplayName() + ": " + event);
  5. }
  6.  
  7. // Decorate event as an ApplicationEvent if necessary
  8. ApplicationEvent applicationEvent;
  9. if (event instanceof ApplicationEvent) {
  10. applicationEvent = (ApplicationEvent) event;
  11. }
  12. else {
  13. applicationEvent = new PayloadApplicationEvent<Object>(this, event);
  14. if (eventType == null) {
  15. eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
  16. }
  17. }
  18.  
  19. // Multicast right now if possible - or lazily once the multicaster is initialized
  20. if (this.earlyApplicationEvents != null) {
  21. this.earlyApplicationEvents.add(applicationEvent);
  22. }
  23. else {
  24. getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); // 通过事件广播器广播事件
  25. }
  26.  
  27. // Publish event via parent context as well...
  28. if (this.parent != null) {
  29. if (this.parent instanceof AbstractApplicationContext) {
  30. ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
  31. }
  32. else {
  33. this.parent.publishEvent(event);
  34. }
  35. }
  36. }

  

SimpleApplicationEventMulticaster: 应用事件广播器

  1. @Override
  2. public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
  3. ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
  4. for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { // 根据event和type找到对应的监听器,并通知监听器
  5. Executor executor = getTaskExecutor();
  6. if (executor != null) {
  7. executor.execute(new Runnable() {
  8. @Override
  9. public void run() {
  10. invokeListener(listener, event);
  11. }
  12. });
  13. }
  14. else {
  15. invokeListener(listener, event);
  16. }
  17. }
  18. }

  

4. spring 事件的消费者 ApplicationEventListener extend EventListener

Spring Session event事件分析的更多相关文章

  1. Re:从零开始的Spring Session(一)

    Session和Cookie这两个概念,在学习java web开发之初,大多数人就已经接触过了.最近在研究跨域单点登录的实现时,发现对于Session和Cookie的了解,并不是很深入,所以打算写两篇 ...

  2. Spring Session工作原理

    本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/KCOFv0nRuymkX79-RZi9eg 作者:张正林 目录:1.引入背景2.使用方法3.工作流程 ...

  3. Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理

    Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...

  4. zepto 事件分析1($.Event)

    先看一下zepto事件的函数,在这里,zepto是把zepto对象作为一个立即执行函数的参数传进去的. (function($){ ... ... })(Zepto) 在zepto事件函数中,主要为$ ...

  5. 【Spring】9、Spring中的事件Event

    Spring的ApplicationContext 提供了支持事件和代码中监听器的功能. 我们可以创建bean用来监听在ApplicationContext 中发布的事件.ApplicationEve ...

  6. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  7. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  8. JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换

    本篇博客我们就来聊一下Spring框架中的观察者模式的应用,即事件的发送与监听机制.之前我们已经剖析过观察者模式的具体实现,以及使用Swift3.0自定义过通知机制.所以本篇博客对于事件发送与监听的底 ...

  9. XML配置spring session jdbc实现session共享

    概述 session的基础知识就不再多说. 通常,我们会把一个项目部署到多个tomcat上,通过nginx进行负载均衡,提高系统的并发性.此时,就会存在一个问题.假如用户第一次访问tomcat1,并登 ...

随机推荐

  1. (二)Java工程化--Maven实践

    Maven项目版本号 默认版本号: 1.0-SNAPSHOT 最佳实践是约定该版本为不稳定版本,如果发布一定要删除; 建议的版本规则: 主版本号.次版本号.增量版本号- 如:1.0.0-RELEASE ...

  2. 第九节,MXNet:用im2rec.py将图像打包生成.rec文件

    1.生成.lst文件 制作一个文件路径和标签的列表: import os import sys #第一个参数是输入路径 input_path=sys.argv[1].rstrip(os.sep) #第 ...

  3. JQuery EasyUI 初始

    基于jQuery的用户界面插件集合 1. jQuery easyui提供了一个完整的组件的集合,包括强大的DataGrid,树网格,面板.用户可以使用他们一起,或者只是用一些组件,组合和构建他想要的跨 ...

  4. Python爬虫实战一之爬取QQ音乐

    一.前言   前段时间尝试爬取了网易云音乐的歌曲,这次打算爬取QQ音乐的歌曲信息.网易云音乐歌曲列表是通过iframe展示的,可以借助Selenium获取到iframe的页面元素, 而QQ音乐采用的是 ...

  5. TF-tf.arg_max 介绍

    定义为 def arg_max(input, dimension, name=None) 作用是取行或者列的最大值的位置. input:类型为 float32, float64, int64, int ...

  6. poj 3278 搜索

    描述: Farmer John has been informed of the location of a fugitive cow and wants to catch her immediate ...

  7. PID控制器开发笔记之十三:单神经元PID控制器的实现

    神经网络是模拟人脑思维方式的数学模型.神经网络是智能控制的一个重要分支,人们针对控制过程提供了各种实现方式,在本节我们主要讨论一下采用单神经元实现PID控制器的方式. 1.单神经元的基本原理 单神经元 ...

  8. Jace Config

    一.jace配置 1.按照Jace 的默认IP配置自己电脑的IP网段(同一个网段),连接上之后使用默认的密码登录,导入tridiumEMEA…..的授权文件,之后创建Station,选择需要的协议驱动 ...

  9. 【工具】idea工具 java代码 gbk转utf8

    idea工具 https://github.com/downgoon/gbk2utf8 安装在目录下: /usr/local/gbk2utf8/bin 进入目录后直接执行 gbk2utf8 sourc ...

  10. linux 查看java的安装路径

    在linux下,如何找java的安装路径 han@ubuntu:/etc$ whereis java java: /usr/bin/java /usr/share/java /usr/lib/jvm/ ...