共计 3159 个字符,预计需要花费 8 分钟才能阅读完成。
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, 在其中的就走异步,否则走同步。