SpringBoot 异步事件实现异步(ApplicationEventPublisher、ApplicationEvent)
当把一个事件发布到Spring提供的ApplicationContext
中,被监听器侦测到,就会执行对应的处理方法。
实现步骤:
- 自定义发布的事件类,需要继承 ApplicationEvent 或者PayloadApplicationEvent(该类也仅仅是对ApplicationEvent的一层封装)
- 监听事件 使用注解 @EventListener 或者 自定义监听器在主函数添加监听器
- s使用ApplicationEventPublisher 或者 实现其接口的子类 发布自定义事件 (@Autowired注入即可)
一、事件本身 ApplicationEvent
事件是一个自定义的类,需要继承Spring提供的ApplicationEvent
。
import com.alibaba.fastjson.JSONObject;
import org.springframework.context.ApplicationEvent;
/**
* 自定义 事件
* @author 王泽华
* 2019/10/22 14:59
*/
public class EsSaveEvent extends ApplicationEvent {
private JSONObject data;
public EsSaveEvent(JSONObject source) {
super(source);
this.data = source;
}
public JSONObject getData() {
return data;
}
}
二、事件监听
1、自定义监听器
基本方法是实现ApplicationListener
接口,自定义一个监听器,实现onApplicationEvent()
方法,然后添加到ApplicationContext
。
import org.springframework.context.ApplicationListener;
public class MyListener implements ApplicationListener<EsSaveEvent> {
@Override
public void onApplicationEvent(EsSaveEvent event) {
//事件处理
System.out.print("监听到MyEvent事件");
}
}
注意:需要在springboot 启动类添加监听器,如下所示:
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
SpringBoot的启动类中添加监听器
application.addListeners(new MyListener());
application.run(args);
}
2、使用注解@EventListener
(推荐):
原理就是通过扫描这个注解,创建监听器并添加到ApplicationContext
。
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
/**
* @author :王泽华
* @Title: EventListener
* @date 2019/10/2214:18
*/
@Component
public class EventListener {
//监听事件
@org.springframework.context.event.EventListener
public void listenEvent(EsSaveEvent event) {
//可以添加事务处理
//divide(event);
JSONObject object = event.getData();
//对数据进行处理
System.out.println("data:"+object.toJSONString());
}
}
//在监听器中重新开一个事务(可选)
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void divide(EsSaveEvent event) {
System.out.println("事务处理");
}
}
三、事件发布
事件发布可以用springboot内部类 也可以自定义
1、直接注入 ApplicationEventPublisher
使用 ApplicationEventPublisher,注入ApplicationEventPublisher接口,调用publisher.publishEvent(new EsSaveEvent(data)) 发布事件。
@Autowired
private ApplicationEventPublisher publisher;
public test(){
JSONObject data=new JSONObject();
publisher.publishEvent(new EsSaveEvent(data));
}
2、自定义事件发布类(继承ApplicationEventPublisher)
A、实现 ApplicationEventPublisher
import com.alibaba.fastjson.JSONObject;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
@Component
public class EventService implements ApplicationEventPublisherAware {
public ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public String doEventWork(String msg) {
JSONObject data=new JSONObject();
data.put("message","------------publish event:" + msg);
EsSaveEvent event = new EsSaveEvent(data);
publisher.publishEvent(event);
return "OK";
}
}
B、测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class EventServiceTest {
@Autowired
private EventService service;
@Test
public void eventTest() {
String msg="Java Code";
service.doEventWork(msg);
}
}
四、注意事项:
1、如果2个事件之间是继承关系,会先监听到子类事件,处理完再监听父类。
2、监听器方法一定要try-catchy异常,否则会造成发布事件(有事务的)的方法进行回滚
3、可以使用@Order注解控制多个监听器的执行顺序,@Order 传入的值越小,执行顺序越高