從需求開始
一個簡單的場景,就是使用者注冊成功後,發短信通知和發郵件通知,其實這樣的場景就是兩種處理情況
- 注冊成功後起一個線程執行發短信和發郵件通知
- 發送使用者ID到mq,然後mq去執行
也許還有其他,那就是我的知識盲區了。其實如果正規的話這種耗時的操作應該是使用MQ,但是使用MQ其實無形之間就增加了系統的複雜性,那麼此時可以使用ApplicationEventPublisher代替MQ
源碼下載下傳
ChaiRongD/Demooo - Gitee.com
代碼:注冊使用者然後發短信這樣的場景
controller
@GetMapping("/insert")
public Object insertMessage(){
//注冊使用者
Student student=new Student();
student.setId(1);
student.setName(LocalDateTime.now().toString());
eventPublisher.publishEvent(new StudentEvent(this,student));
return 1;
}
事件類
@Getter
public class StudentEvent extends ApplicationEvent {
private Student student;
public StudentEvent(Object source,Student student) {
super(source);
this.student = student;
}
}
實體類
@Data
public class Student {
private Integer id;
private String name;
}
處理類
@Component
public class EventHandleListener {
@EventListener
public void handleEvent(StudentEvent studentEvent) throws Exception {
System.out.println("哒哒哒");
System.out.println("哒哒哒");
System.out.println("哒哒哒");
System.out.println(studentEvent.getStudent());
}
}
源碼分析:為什麼能走到自定義的EventHandleLister
其實就是下面的一行代碼,跟一下就行
eventPublisher.publishEvent(new StudentEvent(this,student));
一直跟就到了AbstractApplicationContext
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// 省略
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
//擷取多點傳播器,然後執行派發,跟此處的multicastEvent方法
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// 省略
}
//SimpleApplicationEventMulticaster
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}