Spring 学习之扩展点总结之自定义事件(三)

Spring 源码系列

1、Spring 学习之扩展点总结之后置处理器(一)
2、Spring 学习之扩展点总结之后置处理器(二)
3、Spring 学习之扩展点总结之自定义事件(三)
4、Spring 学习之扩展点总结之内置事件(四)
5、Spring 学习之扩展点总结之@Import(五)
6、Spring 学习之AOP总结之基础介绍(六)
7、Spring 学习之AOP总结之实现代理(七)
8、SpringBoot 学习之自动配置基本原理(八)
9、SpringBoot 学习之启动原理(九)
10、ElasticSearch学习随笔之SpringBoot Starter 操作
11、图数据库 Neo4j 学习之SpringBoot整合
12、SpringBoot 学习之常用 Filter / Advice 总结
13、SpringBoot+FastJson 优雅的过滤 Response Body
14、Spring Security + Oauth2 认证授权

前言

在 Spring学习之扩展点总结(二)介绍了 InitializingBean 和 BeanPostProcessor 的异同点和FactoryBean 和 BeanFactory 的区别。
Spring 除了这些扩展点还提供了 Event 事件操作,本文主要介绍这些事件的操作。

一、什么是 Event?

Spring 的事件就类似于一个活动,比如我们平时举办一个活动或者是某个音乐会,有主持人,指挥员,各种乐器手组成,音乐会开始,指挥员挥舞着手中的指挥棒,下面的各个乐器手就会弹奏不同的音律,这样配合之下,美妙的音乐就产生了。
Spring 事件的核心思想就是监听者模式,Spring事件体系包括三个组件:事件、事件监听器、事件广播器

二、自定义事件发布

自定义事件是 Spring 提供的 ApplicationListener 事件监听接口和 ApplicationEvent 事件抽象类实现的,具体看代码。

2.1 基于 ApplicationListener 接口创建事件监听

1、创建一个事件

新建 OrderEvent 类并且继承 ApplicationEvent 类,就是一个事件类。

public class OrderEvent extends ApplicationEvent {

	private static final long serialVersionUID = 7099057708183571938L;

	private String name;

	public OrderEvent(Object source, String name) {
		super(source);
		this.name = name;
	}

	public String getName() {
		return name;
	}

	/**
	 * Create a new {@code ApplicationEvent}.
	 *
	 * @param source the object on which the event initially occurred or with
	 *               which the event is associated (never {@code null})
	 */
	public OrderEvent(Object source) {
		super(source);
	}
}

2、 创建一个事件监听器

新建一个 OrderEventListener 并且实现了 ApplicationListener 事件监听接口并且复写 onApplicationEvent 方法,并且需要交给 Spring 管理,所以要有@Component注解 。
ApplicationListener 接口继承了 EventListener 事件接口。

@Component
public class OrderEventListener implements ApplicationListener<OrderEvent> {

	@Override
	public void onApplicationEvent(OrderEvent event) {
		if(event.getName().equals("order")){
			System.out.println("进行下单减库存......");
		}
	}
}

3、 事件发布

我们直接在 main 方法中,实例化 Spring 容器,然后用容器提供的 publishEvent 方法把这个事件发布。

@ComponentScan("com.self.test.event")
public class MainStartApp {

	public static void main(String[] args) throws Exception {
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainStartApp.class);
		OrderEventListener bean = applicationContext.getBean(OrderEventListener.class);
		Order order = new Order(1, "开心药");
		applicationContext.publishEvent(new OrderEvent(order, "order"));
		System.out.println("事件已发布...");
	}
}

4、 执行结果
发布事件成功

从执行结果来看,打印了 “进行下单减库存…” 这句话,这句话是 OrderEventListener 事件监听器的事件方法打印的。

2.2 基于 @EventListener 注解添加事件

基于注解添加事件和基于 ApplicationListener 接口添加事件基本一致,唯一不同的就是基于注解添加事件不去实现 ApplicationListener 接口,只需要在具体事件方法上添加 @EventListener 注解即可,代码如下:

@Component
public class OrderEventListener {

	@EventListener(OrderEvent.class)
	public void onApplicationEvent(OrderEvent event) {
		if(event.getName().equals("order")){
			System.out.println("进行下单减库存......");
		}
	}
}

执行测试结果如下:
事件发布成功
运行结果和 基于 ApplicationListener 接口添加的事件一样。

2.3 添加多个事件监听器

Spring发布一个事件后,不是只有一个监听器可以监听到,可以有好多个监听器同时监听,比如上面的减库存监听器,同时还可以有扣款监听器,减积分监听器,实现起来也很方便,只需要继续添加其他的监听器就ok,其他的都不需要改动。

@Component
public class OrderEventListener2 {

	@EventListener(OrderEvent.class)
	public void onApplicationEvent(OrderEvent event) {
		if(event.getName().equals("order")){
			System.out.println("进行下单加积分......");
		}
	}
}
@Component
public class OrderEventListener3 {

	@EventListener(OrderEvent.class)
	public void onApplicationEvent(OrderEvent event) {
		if(event.getName().equals("order")){
			System.out.println("进行下单扣款......");
		}
	}
}

执行测试结果:
多个监听器执行结果

从执行结果看到,新添加的 加积分监听器、扣款监听器 都执行了。

2.4 异步事件添加

我们只需要一个注解就可以把前面的同步事件改为异步事件执行,那就是 @Async 注解,只需要在事件监听方法上面加上这个注解,这些事件监听器就会异步执行,具体看代码:

1、修改事件监听器为异步

@Component
public class OrderEventListener2 {

	@Async
	@EventListener(OrderEvent.class)
	public void onApplicationEvent(OrderEvent event) {
		if(event.getName().equals("order")){
			System.out.println("进行下单加积分......");
		}
	}
}

2、需要开启异步操作

如果想异步执行事件监听器,不但要在事件监听器上面添加 @Async 注解,还需要用 @EnableAsync 开启异步执行,我就在主类 MainStartApp 上面添加了,因为我的主类也相当于一个配置类。

@ComponentScan("com.self.test.event")
@EnableAsync
public class MainStartApp {

	public static void main(String[] args) throws Exception {
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainStartApp.class);
		OrderEventListener bean = applicationContext.getBean(OrderEventListener.class);
		Order order = new Order(1, "开心药");
		applicationContext.publishEvent(new OrderEvent(order, "order"));
		System.out.println("事件已发布...");
	}
}

执行测试结果:
异步事件执行结果

从执行结果中可以看出,加积分 和 扣款 操作在 事件发布之后执行的,而 减库存 操作则是在 事件发布时就执行了。

三、总结

本文主要对 Spring 的自定义事件进行了使用介绍,时间长了难免忘记。Spring 的事件除了自定义事件供我们使用之外,还提供了内置事件,内置事件功能也很强大,供我们修改或操作 Spring 容器里面的一些东西,具体请移步 Spring 学习之扩展点总结(四)内置事件。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值