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,在其中的就走异步,否则走同步。