Spring ApplicationContext(八)事件监听机制

Spring ApplicationContext(八)事件监听机制

本节则重点关注的是 Spring 的事件监听机制,主要是第 8 步:多播器注册;第 10 步:事件注册。

public void refresh() throws BeansException, IllegalStateException {
    // 8. 注册多播器,事件监听器的管理者
    initApplicationEventMulticaster();
    // 9. 专门留给子类初始化其它 bean 用,这是一个空的方法
    onRefresh();
    // 10. 注册监听器
    registerListeners();
}

事件定义如下,实现了 JDK 的规范 EventListener

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    // 监听 event 事件
    void onApplicationEvent(E event);
}

一、ApplicationListener 实战

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("接收的事件:" + event);
    }
}

运行后结果如下:

接收的事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.support.ClassPathXmlApplicationContext@16eabae: startup date [Sun Jul 29 12:41:42 CST 2018]; root of context hierarchy]

二、ApplicationEventMulticaster 多播器的初始化

ApplicationContext 中 refresh() 第 8 步 initApplicationEventMulticaster() 进行多播器的初始化工作

源代码【AbstractApplicationContext】

protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
}

三、ApplicationListener 注册

ApplicationContext 中 refresh() 第 10 步 registerListeners() 进行事件监听者的注册工作。

源代码【AbstractApplicationContext】

protected void registerListeners() {
    // 1. 注册静态指定的侦听器
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 2. 注册 ApplicationListener
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 3. Publish early application events
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

四、ApplicationEvent 事件发布

源代码【AbstractApplicationContext】

public void publishEvent(ApplicationEvent event) {
    publishEvent(event, null);
}

public void publishEvent(Object event) {
    publishEvent(event, null);
}

protected void publishEvent(Object event, ResolvableType eventType) {
    Assert.notNull(event, "Event must not be null");
   
    // 1. 如果 event 不是 ApplicationEvent,则需要进行封装成 PayloadApplicationEvent
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
        applicationEvent = (ApplicationEvent) event;
    }
    else {
        applicationEvent = new PayloadApplicationEvent<Object>(this, event);
        if (eventType == null) {
            eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
        }
    }

    // 2. 发布事件 event,如果多播器懒加载,还没有初始化则将该事件先放到 earlyApplicationEvents 容器中
    //    等待多播器创建好了再发布事件 ???
    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    }
    else {
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }

    // 3. 父容器中也需要发布该事件 event
    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext) {
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        }
        else {
            this.parent.publishEvent(event);
        }
    }
}

每天用心记录一点点。内容也许不重要,但习惯很重要!

posted on 2019-02-23 18:23  binarylei  阅读(990)  评论(0编辑  收藏  举报

导航