深入理解Spring的容器内事件发布监听机制(4)

业务场景在2.1中已经介绍过了,这里就不在啰嗦。基于Spring框架来实现对自定义事件的监听流程十分简单,只需要三部:1.自定义事件类 2.自定义事件监听器并向容器注册 3.发布事件

1.自定任务结束事件
定义一个任务结束事件TaskFinishEvent2,该类继承抽象类ApplicationEvent来遵循容器事件规范。

/**
 * @author: takumiCX
 * @create: 2018-11-04
 **/
public class TaskFinishEvent2 extends ApplicationEvent {
    /**
    * Create a new ApplicationEvent.
    *
    * @param source the object on which the event initially occurred (never {@code null})
    */
    public TaskFinishEvent2(Object source) {
        super(source);
    }
}

2.自定义邮件服务监听器并向容器注册
该类实现了容器事件规范定义的监听器接口,通过泛型参数指定对上面定义的任务结束事件进行监听,通过@Component注解向容器进行注册

/**
 * @author: takumiCX
 * @create: 2018-11-04
 **/
@Component
public class MailTaskFinishListener2 implements ApplicationListener<TaskFinishEvent2> {

private String emial="takumiCX@163.com";
   
    @Override
    public void onApplicationEvent(TaskFinishEvent2 event) {
       
        System.out.println("Send Emial to "+emial+" Task:"+event.getSource());
       
    }
}

3.发布事件
从上面对Spring事件监听机制的类结构分析可知,发布事件的功能定义在ApplicationEventPublisher接口中,而ApplicationContext继承了该接口,所以最好的方法是通过实现ApplicationContextAware接口获取ApplicationContext实例,然后调用其发布事件方法。如下所示定义了一个发布容器事件的代理类

/**
 * @author: takumiCX
 * @create: 2018-11-04
 **/
@Component
public class EventPublisher implements ApplicationContextAware {

private ApplicationContext applicationContext;

//发布事件
    public void publishEvent(ApplicationEvent event){

applicationContext.publishEvent(event);
    }

@Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
}

在此基础上,还可以自定义一个短信服务监听器,在任务执行结束时发送短信通知用户。过程和上面自定义邮件服务监听器类似:实现ApplicationListner接口并重写抽象方法,然后通过注解或者xml的方式向容器注册。

4.Spring事件监听源码解析

Spring事件监听机制离不开容器IOC特性提供的支持,比如容器会自动创建事件发布器,自动识别用户注册的监听器并进行管理,在特定的事件发布后会找到对应的事件监听器并对其监听方法进行回调。Spring帮助用户屏蔽了关于事件监听机制背后的很多细节,使用户可以专注于业务层面进行自定义事件开发。然而我们还是忍不住对其背后的实现原理进行一番探讨,比如:

1.事件发布器ApplicationEventMulticaster是何时被初始化的,初始化过程中都做了什么?

2.注册事件监听器的过程是怎样的,容器怎么识别出它们并进行管理?

3.容器发布事件的流程是怎样的?它如何根据发布的事件找到对应的事件监听器,事件和由该事件触发的监听器之间的匹配规则是怎样的?

为了对以上问题进行解答,我们不得不深入源码层面一探究竟。

4.1 初始化事件发布器流程

真正的事件发布器是ApplicationEventMulticaster,它定义在AbstractApplicationContext中,并在ApplicationContext容器启动的时候进行初始化。在容器启动的refrsh()方法中可以找到初始化事件发布器的入口方法,如下图所示

深入理解Spring的容器内事件发布监听机制

protected void initApplicationEventMulticaster() {
  ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  // 判断beanFactory里是否定义了id为applicationEventMulticaster的bean,默认是没有的
  if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
  this.applicationEventMulticaster =
    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
  if (logger.isDebugEnabled()) {
    logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
  }
  }
  else {
      //一般情况会走这里,创建一个SimpleApplicationEventMulticaster并交由容器管理
  this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
  beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
  if (logger.isDebugEnabled()) {
    logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
      APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
      "': using default [" + this.applicationEventMulticaster + "]");
  }
  }
 }

这里会根据核心容器beanFactory中是否有id为applicationEventMulticaster的bean分两种情况:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8aa7eccef7a6ee573b4af64ab1388374.html