spring事件发布
spring事件接口和注解
1.spring事件中,可以发布原生的对象详细,也可以通过继承ApplicationEvent实现事件类。
- ApplicationListener<E extends ApplicationEvent> 接口
所有被spring托管的bean中,实现了该接口的类. - @EventListener(Clazz)
直接发布原生对象,该对象不需要继承ApplicationEvent接口。在监听该事件时,直接使用注解标注自己接受的类型即可。
@Component
@Scope("prototype")
public class PersonEvent {
@EventListener(Person.class)
@Order(1)
public void printPerson(Person person) throws Exception{
System.out.println(person.toString());
}
@Setter
@Getter
@ToString
public static class Person {
private String name;
private int age;
private String address;
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
}
}
=======
private ApplicationContext applicationContext;
@Test
public void test(){
PersonEvent.Person person = new PersonEvent.Person("test", 3031, "wuhan");
applicationContext.publishEvent(person);
}
2.异步事件和同步事件
spring事件的发布流程,ApplicationContext 继承 ApplicationEventPublisher接口,提供对外的发布接口。AbstractApplictionContext内部提供了一个applicationEventMulticaster。在容器refresh时,会执行initApplicationEventMulticaster;
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No 'applicationEventMulticaster' bean, using [" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
spring内部提供SimpleApplicationEventMulticaster内部的线程池没有初始化,所以spring的事件默认是同步事件。如果想要实现异步事件也很简单。直接向spring容器注册一个SimpleApplicationEventMulticaster即可。注意bean的名称为applicationEventMulticaster
@Bean(name = "applicationEventMulticaster")
public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
SimpleApplicationEventMulticaster eventMulticaster
= new SimpleApplicationEventMulticaster();
SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new SimpleAsyncTaskExecutor();
simpleAsyncTaskExecutor.setConcurrencyLimit(20);
eventMulticaster.setTaskExecutor(simpleAsyncTaskExecutor);
return eventMulticaster;
}
SimpleApplicationEventMulticaster事件分发器的分发流程
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
Executor executor = this.getTaskExecutor();
Iterator var5 = this.getApplicationListeners(event, type).iterator();
while(var5.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var5.next();
if (executor != null) {
executor.execute(() -> {
this.invokeListener(listener, event);
});
} else {
this.invokeListener(listener, event);
}
}
}
从代码中看出,只要配置了异步线程池,所有的事件都会异步执行。
存在可能的集中需求问题
同步事件时,事件监听有特定的执行顺序怎么处理
使用spring在处理监听listener时会进行sort, AnnotationAwareOrderComparator.sort(allListeners);所以可以通过@Order注解实现
如果不想所有的事件都异步执行,有些异步,有些同步怎么处理
自己覆盖SimpleApplicationEventMulticaster的multicastEvent分发方法,比如将异步事件类型加入全局的map,在其中的就走异步,否则走同步。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。