网站你应该明白我的意思吗,晋城商城网站开发设计,凡客诚品 v官网,化妆品设计网站事件机制是Spring的一个功能#xff0c;目前我们使用了SpringBoot框架#xff0c;所以记录下事件机制在SpringBoot框架下的使用#xff0c;同时实现异步处理。事件机制其实就是使用了观察者模式(发布-订阅模式)。
Spring的事件机制经过如下流程#xff1a;
1、自定义事件…事件机制是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 ApplicationListenerEmailEvent {private static Logger log LoggerFactory.getLogger(EmailEventListener.class);// 异步处理AsyncOverridepublic void onApplicationEvent(EmailEvent event) {log.info(监听到事件--邮箱地址: event.getEmailAddress());//模拟处理的耗时3stry {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 {Autowiredprivate 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);Autowiredprivate EmailEventPublish emailEventPublish;RequestMapping(/event)public void publishEvent(RequestParam String emailAddress) {// 发布事件 -- 采用异步处理emailEventPublish.publishEvent(emailAddress);// 正常该语句先执行log.info(Controller业务处理);}
}结果
访问如下地址
http://localhost:8080/event?emailAddressplf163.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 : 监听到事件--邮箱地址:plf163.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 {NullableOverrideBean(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;}NullableOverridepublic 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 : 监听到事件--邮箱地址:plf163.com
2023-08-04 21:27:39.757 INFO 7848 --- [ taskExecutor-1] c.example.demo.event.EmailEventListener : 事件处理完成
可知是使用我们定义的线程池[ taskExecutor-1] 。
总结
Spring的事件机制是一个很实用的一个功能在监听和异步处理相关的功能比较适合。