zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    }
    

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

  • 相关阅读:
    【电商项目】切图仔——神器插件cutterman
    免费服务器存网站步骤
    【电商项目】代码规范——命名推荐
    【电商项目】图标放在哪个元素里面,字体图标偏下处理方法
    【电商项目】小竖线做法
    iconfont阿里字体使用
    类的成分之三构造器
    面向对象的封装性及权限修饰符
    方法的参数值传递机制
    匿名类对象及可变个数形参的方法
  • 原文地址:https://www.cnblogs.com/binarylei/p/10423695.html
Copyright © 2011-2022 走看看