SpringBoot下使用自定义监听事件的流程分析

 更新时间:2023年08月07日 09:32:18   作者:枫叶梨花  
事件机制是Spring的一个功能,目前我们使用了SpringBoot框架,所以记录下事件机制在SpringBoot框架下的使用,同时实现异步处理,这篇文章主要介绍了SpringBoot下使用自定义监听事件,需要的朋友可以参考下

事件机制是Spring的一个功能,目前我们使用了SpringBoot框架,所以记录下事件机制在SpringBoot框架下的使用,同时实现异步处理。事件机制其实就是使用了观察者模式(发布-订阅模式)。

Spring的事件机制经过如下流程:

  • 1、自定义事件,继承org.springframework.context.ApplicationEvent抽象类
  • 2、定义事件监听器,实现org.springframework.context.ApplicationListener接口
  • 3、在Spring容器中发布事件

SpringBoot的实例程序

实现一个保存用户的时候,向用户提供的邮箱发送一封邮件的功能,同时采用异步处理。

自定义事件

import org.springframework.context.ApplicationEvent;
public class EmailEvent extends ApplicationEvent {
	private static final long serialVersionUID = 3733891603598996786L;
	private String emailAddress;
	public EmailEvent(String emailAddress) {
		super(emailAddress);
		this.emailAddress = emailAddress;
	}
	public String getEmailAddress() {
		return emailAddress;
	}
	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}
}

定义事件监听器

import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class EmailEventListener implements ApplicationListener<EmailEvent> {
	private static Logger log = LoggerFactory.getLogger(EmailEventListener.class);
	// 异步处理
	@Async
	@Override
	public void onApplicationEvent(EmailEvent event) {
		log.info("监听到事件--邮箱地址:" + event.getEmailAddress());
		//模拟处理的耗时3s
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.info("事件处理完成");
	}
}

发布事件

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class EmailEventPublish {
	@Autowired
	private ApplicationContext applicationContext;
	public void publishEvent(String emailAddress) {
		EmailEvent event = new EmailEvent(emailAddress);
		applicationContext.publishEvent(event);
	}
}

调用事件

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.event.EmailEventPublish;
@RestController
public class EventController {
	private static Logger log = LoggerFactory.getLogger(EventController.class);
	@Autowired
	private EmailEventPublish emailEventPublish;
	@RequestMapping("/event")
	public void publishEvent(@RequestParam String emailAddress) {
		// 发布事件 -- 采用异步处理
		emailEventPublish.publishEvent(emailAddress);
		// 正常该语句先执行
		log.info("Controller业务处理");
	}
}

结果

访问如下地址

http://localhost:8080/event?emailAddress=plf@163.com

结果为

2023-08-04 21:21:14.338  INFO 6400 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2023-08-04 21:21:14.338  INFO 6400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2023-08-04 21:21:14.370  INFO 6400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 32 ms
2023-08-04 21:21:14.429  INFO 6400 --- [nio-8080-exec-1] .s.a.AnnotationAsyncExecutionInterceptor : No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either
2023-08-04 21:21:14.534  INFO 6400 --- [nio-8080-exec-1] c.e.demo.controller.EventController      : Controller业务处理
2023-08-04 21:21:14.535  INFO 6400 --- [cTaskExecutor-1] c.example.demo.event.EmailEventListener  : 监听到事件--邮箱地址:plf@163.com
2023-08-04 21:21:17.536  INFO 6400 --- [cTaskExecutor-1] c.example.demo.event.EmailEventListener  : 事件处理完成

上述结果可知是实现了异步处理,先打印了事件之后的程序,等时间到再执行监听程序的代码。

实现异步处理就是在监听事件执行业务代码的方法上添加 @Async 注解,同时在启动类上添加 @EnableAsync 即可。

上面的日志还提到了 TaskExecutor ,这是如果有自定义的线程池就会去调用,如果没有就用默认的。我们也可以自己定义一个 TaskExecutor

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@EnableAsync
@Configuration
public class ThreadPool implements AsyncConfigurer {
	@Nullable
	@Override
	@Bean("taskExecutor")
	public Executor getAsyncExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		// 线程池创建时候初始化的线程数
		executor.setCorePoolSize(10);
		// 线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
		executor.setMaxPoolSize(20);
		// 用来缓冲执行任务的队列
		executor.setQueueCapacity(200);
		// 允许线程的空闲时间60秒
		executor.setKeepAliveSeconds(60);
		// 线程池名的前缀
		executor.setThreadNamePrefix("taskExecutor-");
		// 线程池对拒绝任务的处理策略
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}
	@Nullable
	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return null;
	}
}

结果

2023-08-04 21:27:36.507  INFO 7848 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2023-08-04 21:27:36.507  INFO 7848 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2023-08-04 21:27:36.537  INFO 7848 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 30 ms
2023-08-04 21:27:36.757  INFO 7848 --- [nio-8080-exec-2] c.e.demo.controller.EventController      : Controller业务处理
2023-08-04 21:27:36.757  INFO 7848 --- [ taskExecutor-1] c.example.demo.event.EmailEventListener  : 监听到事件--邮箱地址:plf@163.com
2023-08-04 21:27:39.757  INFO 7848 --- [ taskExecutor-1] c.example.demo.event.EmailEventListener  : 事件处理完成

可知是使用我们定义的线程池[ taskExecutor-1]

总结

Spring的事件机制是一个很实用的一个功能,在监听和异步处理相关的功能比较适合。

到此这篇关于SpringBoot下使用自定义监听事件的文章就介绍到这了,更多相关SpringBoot自定义监听事件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈JDK、JRE、JVM三者之间的关系

    浅谈JDK、JRE、JVM三者之间的关系

    本文主要介绍了浅谈JDK、JRE、JVM三者之间的关系,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Spring中@Configuration和@Component注解的区别及原理

    Spring中@Configuration和@Component注解的区别及原理

    这篇文章主要介绍了Spring中@Configuration和@Component注解的区别及原理,从功能上来讲,这些注解所负责的功能的确不相同,但是从本质上来讲,Spring内部都将其作为配置注解进行处理,需要的朋友可以参考下
    2023-11-11
  • spring boot实现阿里云视频点播上传视频功能(复制粘贴即可)

    spring boot实现阿里云视频点播上传视频功能(复制粘贴即可)

    这篇文章主要介绍了spring boot实现阿里云视频点播上传视频功能(复制粘贴即可),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • Lombok中关于@Data的使用解析

    Lombok中关于@Data的使用解析

    这篇文章主要介绍了Lombok中关于@Data的使用解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • IntelliJ IDEA中properties文件显示乱码问题的解决办法

    IntelliJ IDEA中properties文件显示乱码问题的解决办法

    今天小编就为大家分享一篇关于IntelliJ IDEA中properties文件显示乱码问题的解决办法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • 基于RabbitMQ的简单应用(详解)

    基于RabbitMQ的简单应用(详解)

    下面小编就为大家分享一篇基于RabbitMQ的简单应用(详解),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • Java的微信开发中使用XML格式和JSON格式数据的示例

    Java的微信开发中使用XML格式和JSON格式数据的示例

    这篇文章主要介绍了Java微信开发中使用XML格式和JSON格式数据的示例,注意一下json-lib所需要的jar包,需要的朋友可以参考下
    2016-02-02
  • 解析Java中的定时器及使用定时器制作弹弹球游戏的示例

    解析Java中的定时器及使用定时器制作弹弹球游戏的示例

    这篇文章主要介绍了Java中的定时器及使用定时器制作弹弹球游戏的示例,文中同时也分析了定时器timer的缺点及相关替代方案,需要的朋友可以参考下
    2016-02-02
  • Spring Boot Jwts Token生成方法示例

    Spring Boot Jwts Token生成方法示例

    这篇文章主要为大家介绍了Spring Boot Jwts Token生成方法示例,非适合java初学者,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 详解Java Unsafe如何花式操作内存

    详解Java Unsafe如何花式操作内存

    C++可以动态的分类内存,而java并不能这样,是不是java就不能操作内存呢,其实是有其他办法可以操作内存的,下面就一起看看Unsafe是如何花式操作内存的吧
    2023-08-08

最新评论