先看一段问题代码。如果我们要实现一个主线业务,同时需要做一些支线任务。如果都写在一起,会不太好,我们不希望把主线任务耦合到支线任务里面。
package com.example.springdemo.demos.a17;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* @author zhou
* @version 1.0
* @description TODO
* @date 2025/9/6 21:56
*/
@Configuration
public class TestListener {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestListener.class);
context.getBean(MyService.class).doBusiness();
context.close();
}
@Component
static class MyService{
private static final Logger log = LoggerFactory.getLogger(TestListener.class);
public void doBusiness(){
log.debug("主线业务");
log.debug("发送短信");
log.debug("发送邮件");
}
}
}
Spring提供了事件监听机制去实现主线任务与支线任务的低耦合。实现思路如下:
1.首先需要提供事件对象
static class MyEvent extends ApplicationEvent{
public MyEvent(Object source) {
super(source);
}
}
2.实现Spring提供的事件监听器接口,并指定泛型接口是我们自己写的事件对象。重写里面的方法加上我们自己的逻辑。
@Component
static class SmsApplicationListener implements ApplicationListener<MyEvent>{
private static final Logger log = LoggerFactory.getLogger(SmsApplicationListener.class);
@Override
public void onApplicationEvent(MyEvent event) {
log.debug("发送短信");
}
}
@Component
static class EmailApplicationListener implements ApplicationListener<MyEvent>{
private static final Logger log = LoggerFactory.getLogger(EmailApplicationListener.class);
@Override
public void onApplicationEvent(MyEvent event) {
log.debug("发送邮件");
}
}
3.改造业务代码
注入事件发布器发布事件。
@Component
static class MyService{
private static final Logger log = LoggerFactory.getLogger(TestListener.class);
@Autowired
private ApplicationEventPublisher publisher;
public void doBusiness(){
log.debug("主线业务");
/* log.debug("发送短信");
log.debug("发送邮件");*/
publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
}
}
其中MyEvent
构造函数的参数可以是任何有助于监听器理解"发生了什么"和"需要处理什么"的信息,而不仅仅是方法名。
打印结果:
这里监听器执行支线任务是随机的,而且都是在主线程执行,还有优化空间。