关于spring:spring事件机制

spring事件公布

spring事件接口和注解

1.spring事件中,能够公布原生的对象具体,也能够通过继承ApplicationEvent实现事件类。

  1. ApplicationListener<E extends ApplicationEvent> 接口
    所有被spring托管的bean中,实现了该接口的类.
  2. @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);
            }
        }
    }

从代码中看出,只有配置了异步线程池,所有的事件都会异步执行。

存在可能的集中需要问题

  1. 同步事件时,事件监听有特定的执行程序怎么解决

    应用spring在解决监听listener时会进行sort, AnnotationAwareOrderComparator.sort(allListeners);所以能够通过@Order注解实现

  2. 如果不想所有的事件都异步执行,有些异步,有些同步怎么解决

    本人笼罩SimpleApplicationEventMulticaster的multicastEvent散发办法,比方将异步事件类型退出全局的map,在其中的就走异步,否则走同步。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理