Spring 使用介绍(十一)—— Spring事件
一、简介
spring事件是观察者设计模式的实现,主要有三个元素:
- 事件 spring事件由ApplicationEvent定义
- 监听者 由ApplicationListener定义
- 发布者 由ApplicationEventPublisher定义,而ApplicationContext继承自ApplicationEventPublisher
简单示例:
自定义事件
public class TestEvent extends ApplicationEvent {
private String message;
public TestEvent(Object source) {
this(source, "default message");
}
public TestEvent(Object source, String msg) {
super(source);
this.message = msg;
}
public String getMessage() {
return message;
}
}
监听者
@Component
public class TestListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof TestEvent) {
System.out.println(((TestEvent)event).getMessage());
}
}
}
XML配置
<context:component-scan base-package="cn.matt.event"/>
测试
public class EventTest {
@Test
public void testCustomEvent() {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-context.xml");
context.publishEvent(new TestEvent("", "hello matt"));
}
}
补充:
定义监听者时,可通过泛型指定监听事件类型,因此,上例监听者可定义如下:
@Component
public class TestListener implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent event) {
System.out.println(((TestEvent) event).getMessage());
}
}
二、spring容器事件
spring为容器启动各阶段定义了相关事件,实现如图:

事件说明:
- ContextStartedEvent:ApplicationContext启动后触发的事件(调用start方法)
- ContextStoppedEvent:ApplicationContext停止后触发的事件(调用stop方法)
- ContextClosedEvent:ApplicationContext关闭后触发的事件
- ContextRefreshedEvent:ApplicationContext初始化或刷新完成后触发的事件(容器初始化(如bean的实例化、依赖注入)完成后调用)
使用示例
@Component
public class ApplicationStartUpListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("spring context inited");
}
}
三、事件的执行机制
spring事件的执行机制默认使用单线程同步执行,异步执行可使用@Async注解实现,示例如下(新用户注册):
定义事件
public class RegisterEvent extends ApplicationEvent {
public RegisterEvent(User user) {
super(user);
}
}
定义监听者
// 发生邮件
@Component
public class EmailRegisterListener implements ApplicationListener<RegisterEvent> {
@Async
public void onApplicationEvent(final RegisterEvent event) {
System.out.println(Thread.currentThread().getId() + " **** 注册成功,发送确认邮件给:" + ((User)event.getSource()).getUsername());
}
}
// 赠送积分
@Component
public class PointRegisterListener implements ApplicationListener<RegisterEvent> {
@Async
public void onApplicationEvent(final RegisterEvent event) {
System.out.println(Thread.currentThread().getId() + " **** 注册成功,赠送积分给:" + ((User)event.getSource()).getUsername());
}
}
// 赠送大礼包
@Component
public class PresentRegisterListener implements ApplicationListener<RegisterEvent> {
@Async
public void onApplicationEvent(final RegisterEvent event) {
System.out.println(Thread.currentThread().getId() + " **** 注册成功,赠送大礼包给:" + ((User)event.getSource()).getUsername());
}
}
用户类与业务类
public class User implements Serializable {
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
}
@Service
public class RegisterService {
@Autowired
private ApplicationContext applicationContext; public void register(String username, String password) {
System.out.println(username + "注册成功!");
publishRegisterEvent(new User(username, password));
} private void publishRegisterEvent(User user) {
applicationContext.publishEvent(new RegisterEvent(user));
}
}
配置
<context:component-scan base-package="com.sishuok"/> <!-- 任务调度器 -->
<task:scheduler id="scheduler" pool-size="10"/> <!-- 任务执行器 -->
<task:executor id="executor" pool-size="10"/> <!--开启注解调度支持 @Async @Scheduled-->
<task:annotation-driven executor="executor" scheduler="scheduler" proxy-target-class="true"/>
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-config-register.xml"})
public class RegisterServiceIT {
@Autowired
private RegisterService registerService; @Test
public void testRegister() {
registerService.register("long", "123");
}
} // 输出:
// long注册成功!
// 15 **** 注册成功,发送确认邮件给:long
// 17 **** 注册成功,赠送积分给:long
// 18 **** 注册成功,赠送大礼包给:long
参考:
Spring进阶之路(2)-ApplicationContext容器以及事件机制
Spring 使用介绍(十一)—— Spring事件的更多相关文章
- [转帖]微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务
微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务 http://skaka.me/blog/2016/04/21/springcloud1/ APR 21ST, ...
- 黑马_13 Spring Boot:01.spring boot 介绍&&02.spring boot 入门
13 Spring Boot: 01.spring boot 介绍&&02.spring boot 入门 04.spring boot 配置文件 SpringBoot基础 1.1 原有 ...
- 微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务
http://skaka.me/blog/2016/04/21/springcloud1/ 不同于单一架构应用(Monolith), 分布式环境下, 进行事务操作将变得困难, 因为分布式环境通常会有多 ...
- 黑马_13 Spring Boot:05.spring boot 整合其他技术
13 Spring Boot: 01.spring boot 介绍&&02.spring boot 入门 04.spring boot 配置文件 05.spring boot 整合其他 ...
- 黑马_13 Spring Boot:04.spring boot 配置文件
13 Spring Boot: 01.spring boot 介绍&&02.spring boot 入门 04.spring boot 配置文件 05.spring boot 整合其他 ...
- [翻译]Spring框架参考文档(V4.3.3)-第二章Spring框架介绍 2.1 2.2 翻译--2.3待继续
英文链接:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/overview.ht ...
- 一、Spring Cloud介绍
springcloud 介绍 研究了一段时间spring boot了准备向spirng cloud进发,公司架构和项目也全面拥抱了Spring Cloud.在使用了一段时间后发现Spring Clou ...
- Spring入门介绍
概述 下载地址:https://repo.spring.io/release/org/springframework/spring/ spring是开源的轻量级框架 spring核心的主要两部分 AO ...
- Spring Cloud第十一篇 | 分布式配置中心高可用
本文是Spring Cloud专栏的第十一篇文章,了解前十篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Cl ...
随机推荐
- redis底层设计(三)——redis数据类型
今天我们来看一下redis的数据类型.既然redis的键值对可以保存不同类型的值,那么很自然就需要对键值对的类型进行检查以及多态处理.下面我们将对redis所使用的对象系统进行了解,并分别观察字符串. ...
- Flask入门的第一个项目进阶版
前言: 此次版本增加[一对多]数据库关系和动态路由设置. 一.数据库设计 environments表与variable1表的关系为:一对多.variable1.env_id设置为外键,与environ ...
- Jenkins-job之间依赖关系配置
使用场景: 想要在某APP打新包之后,立即执行自动化测试的job来验证该新包. 比如Job A 执行完执行Job B ,如下图所示,如何建立依赖呢? 1.配置上游依赖 构建触发器-配置如下信息: 选择 ...
- tornado设置cookie并加密
最近看看tornado,遇到了sso的东西,了解下如何设置cookie 1.基本cookie set_cookie 方法在用户的浏览中设置 cookie: get_cookie 方法在用户的浏览中获取 ...
- Eclipse启动错误JVM terminated. exit code 1解决方法
现象: 前一天eclipse还用得好好的,但今天就不能用了,怎么回事? 解决方案: 请先参考其它网络资料:http://www.baidu.com/s?wd=eclipse+jvm+terminate ...
- 【转】给word中的代码着色
基本操作 1)用Notepad++直接编辑代码文件,注意文件后缀,比如.cpp是C++程序,.m是Matlab,linux文件是.sh,写对后缀表示的文件类型,才有对应的语法高亮效果. 2)选中需要的 ...
- Python之操作Excel
使用之前先导入三个模块: import xlwt #只能写Excel import xlrd #只能读Excel import xlutils #修改Excel,在原来的基础上修改 一.写EXCEL ...
- jdk环境变量配置注意事项
cmd 运行java -version 显示错误 Registry key 'Software\JavaSoft\Java Runtime Environment\CurrentVersion'has ...
- python与C,在写程序时踩过的坑!
1. python与C有很多相似之处, 其一就是指针的大量应用, 因此在使用临时变量保存数据, 并将临时变量传递给其他变量时需要创建内存; 例如,在C中, char *temp 每次获取到不同的字 ...
- IdentityServer4【Introduction】之术语
术语 在规范.文档和对象模型中使用了一些你应该了解的术语. IdentityServer IdentityServer是一个OpenID Connect的提供者,它实现了OpenID Connect和 ...