spring中ApplicationListener源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

最近做一个功能,需要在整个服务器容器加载完成就触发执行,这个时候我只需要实现ApplicationListener即可。spring的这个接口就是给一个观察的入口,可以在各个阶段去触发相应的操作。不难看出这就是典型的设计模式之观察者模式。这次我们以观察者的观点去分析一下ApplicationListener。

    /** * Interface to be implemented by application event listeners. * Based on the standard {@code java.util.EventListener} interface * for the Observer design pattern. * * <p>As of Spring 3.0, an ApplicationListener can generically declare the event type * that it is interested in. When registered with a Spring ApplicationContext, events * will be filtered accordingly, with the listener getting invoked for matching event * objects only. * * @author Rod Johnson * @author Juergen Hoeller * @param <E> the specific ApplicationEvent subclass to listen to * @see org.springframework.context.event.ApplicationEventMulticaster */
    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

        /** * Handle an application event. * @param event the event to respond to */
        void onApplicationEvent(E event);

    }

Rod Johnson大神也在注释里写清楚了这个功能就是基于观察者模式,并且用户可以在实现类中指定自己感兴趣的事件观察。这个就是所有观察者的抽象接口,这个接口是给客户端使用的,客户端只是对接口透明,对具体的需要通知的对象是动态注入的。一旦观察者感兴趣的事件发生,客户端就会调用接口的方法通知。
这个通知方法,就是在:org.springframework.context.event.SimpleApplicationEventMulticaster中的:

    protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
            ErrorHandler errorHandler = getErrorHandler();
            if (errorHandler != null) {
                try {
                    listener.onApplicationEvent(event);
                }
                catch (Throwable err) {
                    errorHandler.handleError(err);
                }
            }
            else {
                listener.onApplicationEvent(event);
            }
        }

这里只是通知一个观察者,具体要通知哪些观察者在该类的父类org.springframework.context.event.SimpleApplicationEventMulticaster定义一种事件类型的观察者有哪些(ApplicationListener):

    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
            ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
            for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
                Executor executor = getTaskExecutor();
                if (executor != null) {
                    executor.execute(new Runnable() {
                        @Override
                        public void run() {
                            invokeListener(listener, event);
                        }
                    });
                }
                else {
                    invokeListener(listener, event);
                }
            }
        }

所有的监听器的注册在org.springframework.context.support.AbstractApplicationContext的refresh()方法当中的registerListener()方法,该方法基本完成了容器的初始化:

    protected void registerListeners() {
            // Register statically specified listeners first.
            for (ApplicationListener<?> listener : getApplicationListeners()) {
                getApplicationEventMulticaster().addApplicationListener(listener);
            }

            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let post-processors apply to them!
            String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
            for (String listenerBeanName : listenerBeanNames) {
                getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
            }

            // Publish early application events now that we finally have a multicaster...
            Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
            this.earlyApplicationEvents = null;
            if (earlyEventsToProcess != null) {
                for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                    getApplicationEventMulticaster().multicastEvent(earlyEvent);
                }
            }
        }

当容器初始化结束后就会调用finishRefresh(),该事件会触发一系列操作,其中就包括通知观察者,即监听器:

    protected void publishEvent(Object event, ResolvableType eventType) {
            Assert.notNull(event, "Event must not be null");
            if (logger.isTraceEnabled()) {
                logger.trace("Publishing event in " + getDisplayName() + ": " + event);
            }

            // Decorate event as an ApplicationEvent if necessary
            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());
                }
            }

            // Multicast right now if possible - or lazily once the multicaster is initialized
            if (this.earlyApplicationEvents != null) {
                this.earlyApplicationEvents.add(applicationEvent);
            }
            else {
                getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
            }

            // Publish event via parent context as well...
            if (this.parent != null) {
                if (this.parent instanceof AbstractApplicationContext) {
                    ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
                }
                else {
                    this.parent.publishEvent(event);
                }
            }
        }

以上代码是根据事件去通知对应的监听器。这里的具体情况是在finishRefresh()传入了容器加载完成事件:
这样就去调用对这个事件感兴趣的监听器。

            // Publish the final event.
            publishEvent(new ContextRefreshedEvent(this));

这里完成接口调用通知。

    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
            ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
            for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
                Executor executor = getTaskExecutor();
                if (executor != null) {
                    executor.execute(new Runnable() {
                        @Override
                        public void run() {
                            invokeListener(listener, event);
                        }
                    });
                }
                else {
                    invokeListener(listener, event);
                }
            }
        }

这样就用观察者模式实现了spring的整个事件监听功能。


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring中ApplicationListener源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏