1.本例子 基于 “张三” 考上清华了 ,非常高兴 要分别通过 邮件 和短信 等不同的方式 通知到家长为背景。
2.首先 是 创建个 事件类
/** * 通知事件的载体,以Student作为 事件的内容 */ public class StudentStatusUpdateEvent extends ApplicationEvent { public StudentStatusUpdateEvent(Student source) { super(source); } }
3.创建三个 监听事件的 监听器 分别去处理
3.1---------
/** * 无序事件监听器,库存服务监听器 */ @Service public class StockPaymentStatusUpdateListener implements ApplicationListener<StudentStatusUpdateEvent> { @Override @Async public void onApplicationEvent(StudentStatusUpdateEvent paymentStatusUpdateEvent) { Student student=(Student)paymentStatusUpdateEvent.getSource(); System.out.println("存库 "+student.toString()); } }
3.2-------------------------------------------
/** * 短信服务,有序监听器 */ @Service public class SmsPaymentStatusUpdateListener extends AbstractPaymentStatusListener implements SmartApplicationListener { //定义监听器的级别 这里如果开启了异步 则级别无效 @Override public int getOrder() { return 2; } @Override @Async public void onApplicationEvent(ApplicationEvent applicationEvent) { Student student=(Student)applicationEvent.getSource(); System.out.println("Thread: " + Thread.currentThread().getName()+ " 短信服务, " + student.getName()+"考上清华啦!!!!"); } }
3.3------------------------
/** * 有序监听器,邮件服务监听器 */ @Service public class MailPaymentStatusUpdateListener extends AbstractPaymentStatusListener implements SmartApplicationListener { // 排序,数字越小执行的优先级越高 @Override public int getOrder() { return 1; } @Override @Async public void onApplicationEvent(ApplicationEvent applicationEvent) { Student student=(Student)applicationEvent.getSource(); System.out.println("Thread: " + Thread.currentThread().getName()+ " 邮件服务, " + student.getName()+"考上清华啦!!!!"); } }
3.4-----------------------
/** * 有序监听器,抽象类实现事件源以及事件的通用判断 */ public abstract class AbstractPaymentStatusListener implements SmartApplicationListener { @Override public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) { return aClass == StudentStatusUpdateEvent.class; } @Override public boolean supportsSourceType(Class<?> sourceType) { return sourceType == Student.class; } }
4.接下来 是具体的业务要用到的类
4.1---------------student
/** * 实体类,将作为事件实体 */ @Data @ToString @AllArgsConstructor public class Student { private int id; private String stauts; private String name; }
4.2----------------------controller
@RestController public class StudentController { @Autowired StudentService paymentService; @RequestMapping("/notification") public void notification(){ paymentService.notification(1,"12"); } }
4.3--------------service
@Service public class StudentService { @Autowired ApplicationContext applicationContext; public void notification(int id, String status) { // ...... 省略处理业务逻辑代码 Student paymentInfo = new Student(id, status,"张三"); // 发布事件 此处以张三考上清华了 需要分别 以短信通知 邮件通知 和存储 // 分别由三个不同的事件监听器来监听这个事件 applicationContext.publishEvent(new StudentStatusUpdateEvent(paymentInfo)); } }
5.配置异步线程池 绑定事件
@Configuration @EnableAsync public class AnnotationAsyncConfig implements AsyncConfigurer { /** * 线程池维护线程的最小数量 */ private int corePoolSize =2; /** * 线程池维护线程的最大数量 */ private int maxPoolSize =2; /** * 队列最大长度 */ private int queueCapacity = 100; /** * 获取异步线程池执行对象 */ @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(corePoolSize); taskExecutor.setMaxPoolSize(maxPoolSize); taskExecutor.setQueueCapacity(queueCapacity); //用于调试 taskExecutor.setThreadNamePrefix("AnnotationAsyncExecutor-"); taskExecutor.setWaitForTasksToCompleteOnShutdown(true); //拒绝策略 CallerRunsPolicy 由调用线程处理该任务 taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); taskExecutor.initialize(); return taskExecutor; } }
6.启动springboot 项目notification 调用接口
最终的执行结果:
Thread: AnnotationAsyncExecutor-2 邮件服务, 张三考上清华啦!!!!
Thread: AnnotationAsyncExecutor-1 短信服务, 张三考上清华啦!!!!
存库 Student(id=1, stauts=12, name=张三)