spring事件机制
前置知识补充:
程序里面所谓的“上下文”就是程序的执行环境,打个比方:你就相当于web程序,你的房子就相当于web程序的上下文,你可以在家里放东西,也可以取东西,你的衣食住行都依赖这个房子,这个房子就是你生活的上下文环境~
ServletContext:
ServletContext是web应用级上下文(包含listener,filter,servlet等)。web容器(比如tomcat、jboss、weblogic等)启动的时候,它会为每个web应用程序创建一个ServletContext对象 它代表当前web应用的上下文(注意:是每个web应用有且仅创建一个ServletContext,一个web应用,就是你一个web工程)。一个web中的所有servlet共享一个ServletContext对象,可以通过ServletContext对象来实现Servlet之间的通讯。HttpServlet对象可通过this.getServletContext来获取ServletContext。
ApplicationContext:
//ServletContext和ApplicationContext的区别和联系:https://blog.csdn.net/bai_bug/article/details/80218202
web应用中的spring的上下文,在servletContext初始化后,进行初始化,然后通过ServletContext加载applicationContext.xml。
在web程序中使用spring的时候,我们需要配置:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
在web容器启动时,会触发容器初始化事件,此时ContextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口(这个接口继承ApplicationContext这个接口),确切的说,其实际的实现类是XmlWebApplicationContext。这个就是Spring的IoC容器,在这个IoC容器初始化完毕后,Spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取。
spring事件分类:
总体框图:EventObject抽象类记录事件源,子接口ApplicationEvent记录时间戳

Spring 提供了以下5中标准的事件:
- 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
- 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
在web项目中如果同时集成了spring和springMVC的话,上下文中会存在两个容器,即spring的applicationContext.xml的父容器和springMVC的applicationContext-mvc.xml的子容器。
在通过applicationContext发送通知的时候,事件会被两个容器发布,也就是发送用applicationContext.publishEvent()发送消息,相应的监听者会收到两次
- @Component
- public class BeanFactory implements ApplicationContextAware {
- private static ApplicationContext applicationContext;
- public static <T> T getBean(String beanName, Class<T> clazz) {
- return (T) applicationContext.getBean(beanName);
- }
- /**
- * 通知事件
- *
- * @param applicationEvent
- */
- public static void pushEvent(ApplicationEvent applicationEvent) {
- //获取父容器发送事件
- //ContextLoader.getCurrentWebApplicationContext().publishEvent(applicationEvent);
- applicationContext.publishEvent(applicationEvent);
- }
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
- public static ApplicationContext getApplicationContext() {
- return applicationContext;
- }
- }
解决方案的思路是用父容器去发送通知
- public static void pushEvent(ApplicationEvent applicationEvent) {
- //获取父容器发送事件
- ContextLoader.getCurrentWebApplicationContext().publishEvent(applicationEvent); //ContextLoader内部维护了一个ConcurrentHashMap<ClassLoader,WebApplicationContext>//存的是根容器
- }
-------------------------------------------------正题开始------------------------------------------------
定义一个类实现ApplicationListener<ContextRefreshedEvent>接口,并把该类交给Spring来管理,并在重写方法,实现自己的业务即可,因为ContextRefreshedEvent就是Spring的启动事件,Spring启动完成就会触发该事件.
有许多时候需要自己定义事件与监听器,如果我们都通过注入对象,调用对象对应的方法来处理,那么代码耦合度高.此时我们可以使用Spring的事件机制来处理.//A——>B,A和B耦合,解耦做法:A->C->B,引入中间者C,完成AB解耦
接口简介:
ApplicationEvent : 抽象类,记录了source(事件源)和初始化时间戳:用来定义Event //所有自定义事件都需要继承这个抽象类
ApplicationEventPublisher// ApplicationEventPublisherAware(自定义发布类实现的接口) // ApplicationPublisher等: 发布消息对象,负责发布消息,调度消息的监听器;
ApplicationListener : 负责处理某一类消息;
流程简介:
事件的接收者其实是一个监听器,必须实现ApplicationListener,注意把事件TradeEvent直接写到泛型中(表面此监听器是专门处理该事件的),//首先创建一个监听器,并注册到Spring容器;
其次,在某一个事件发生的时候,创建这个事件对应的消息对象(ApplicationEvent);
最后,通过ApplicationPublisher接口中的publishEvent方法,发布这个消息.//ApplicationContext实现这个接口,并具有调度事件监听器的方法
补充:
ApplicationContext这个接口是Spring的上下文,通常获取Bean就需要这个接口,这个接口并不是直接继承于BeanFactory,其中最著名的是
直接继承了ApplicationPublisher接口,这个接口查看源码可以发现:只有一个方法,那就是主角 void publishEvent(ApplicationEvent event);
Spring提供的基于Aware相关的接口有ApplicationContextAware,ResourceloaderAware,ServletContextAware(注意:Struts2也有这个接口,注意区分),最常用的就这三个,而Spring的事件发布机制需要用到ApplicationContextAware接口。
实现了ApplicationContextAware的Bean,在Bean初始化时将会被注入ApplicationContext实例(因为这个感知接口里有set(ApplictationContext ctx)方法
另外 Spring的事件监听是基于观察者模式
spring事件机制的更多相关文章
- Spring事件机制详解
一.前言 说来惭愧,对应Spring事件机制之前只知道实现 ApplicationListener 接口,就可以基于Spring自带的事件做一些事情(如ContextRefreshedEvent),但 ...
- 深入理解Spring事件机制(一):广播器与监听器的初始化
前言 Spring 从 3.x 开始支持事件机制.在 Spring 的事件机制中,我们可以令一个事件类继承 ApplicationEvent 类,然后将实现了 ApplicationListener ...
- 搞清楚Spring事件机制后:Spring的源码看起来简单多了
本文主讲Spring的事件机制,意图说清楚: 什么是观察者模式? 自己实现事件驱动编程,对标Spring的事件机制 彻底搞懂Spring中的事件机制,从而让大家 本文内容较长,代码干货较多,建议收藏后 ...
- 观察者模式之spring事件机制
ddsspring中的事件机制使用到设计模式中的观察者模式 ,观察者模式有两个概念,1.观察者.被观察者.2.被观察者做出相应得动作,观察者能接收到.不分析设计模式,学习下spring中的事件机制实际 ...
- Spring 事件机制
通过模拟邮件的发送,说明Spring的事件监听机制 事件类 package org.zln.module_chapter2.event; import org.springframework.cont ...
- Spring的事件机制详解
同步事件和异步事件 同步事件:在一个线程里,按顺序执行业务,做完一件事再去做下一件事. 异步事件:在一个线程里,做一个事的同事,可以另起一个新的线程执行另一件事,这样两件事可以同时执行. 用一个例子来 ...
- Spring 中的事件机制
说到事件机制,可能脑海中最先浮现的就是日常使用的各种 listener,listener去监听事件源,如果被监听的事件有变化就会通知listener,从而针对变化做相应的动作.这些listener是怎 ...
- Spring 事件监听机制及原理分析
简介 在JAVA体系中,有支持实现事件监听机制,在Spring 中也专门提供了一套事件机制的接口,方便我们实现.比如我们可以实现当用户注册后,给他发送一封邮件告诉他注册成功的一些信息,比如用户订阅的主 ...
- Spring事件解析
首先介绍Spring事件相关类的关系: 其中EventListener与EventObject均是Java SE的范畴,源码如下: package java.util; public interfac ...
随机推荐
- jstorm集成kafka
本人是spark的拥趸,因为工作中需要用到jstorm,作记录如下. pom.xml <dependencies> <dependency> <groupId>co ...
- 一些网站的meta标签的作用
转载:https://www.cnblogs.com/Lily-nercel/p/6693293.html <!DOCTYPE html> <html lang="en&q ...
- H5 边框:带border的百分比布局
响应式Web设计经常需要我们通过百分比设置组件宽度.如果我们不考虑边框,那么很容易就可以实现,但如果你给每一列以及总宽度都采用百分比设置,那这个时候固定的边框大小就会出来捣乱.下面我们将看到一组方法去 ...
- 一:怎样运行python程序
运行python程序有三种方法: 1,在命令行运行python代码:C:/python27>python hello.py [注:如果没有把PATH环境变量设置为包含这一路径,要确保输入到了 ...
- pta6-17(另类堆栈)
题目链接:https://pintia.cn/problem-sets/1101307589335527424/problems/1101313244872126464 题意:一种新的堆栈,用Top表 ...
- centos 6 下KVM 安装学习之旅
一.虚拟化介绍 虚拟化是云计算的基础.简单的说,虚拟化使得在一台物理的服务器上可以跑多台虚拟机,虚拟机共享物理机的 CPU.内存.IO 硬件资源,但逻辑上虚拟机之间是相互隔离的. 物理机我们一般 ...
- Unity3D游戏贪吃蛇大作战源码休闲益智手机小游戏完整项目
<贪吃蛇大作战>一款休闲竞技游戏,不仅比拼手速,更考验玩家的策略. 视频演示: http://player.youku.com/player.php/sid/XMzc5ODA2Njg1Ng ...
- Jmeter 录制脚本(二)
1)选择WorkBench,右键 Add -> Non-Test Elements -> HTTP(S) Test Script Recorder 2)在HTTP(S) Test Scri ...
- PTA 7-8 哈利·波特的考试(floyd)
哈利·波特要考试了,他需要你的帮助.这门课学的是用魔咒将一种动物变成另一种动物的本事.例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等.反方向变化的魔咒就是简单地将原来的魔咒倒过来念 ...
- Nginx中超时时间配置(转)
本文介绍 Nginx 的 超时(timeout)配置.分享给大家,具体如下: Nginx 处理的每个请求均有相应的超时设置.如果做好这些超时时间的限定,判定超时后资源被释放,用来处理其他的请求,以此提 ...