zoukankan      html  css  js  c++  java
  • srpingboot web

    接上一篇

    一. getRunListeners()

    在run() 方法中调用了 getRunListeners(args) 方法, 先看一下这个方法干了什么

    private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
        return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
                SpringApplicationRunListener.class, types, this, args));
    }

    加载配置 spring.factories 中的配置, 

    # Run Listeners
    org.springframework.boot.SpringApplicationRunListener=
    org.springframework.boot.context.event.EventPublishingRunListener

    然后创建配置中的 EventPublishingRunListener , 封装到  SpringApplicationRunListeners 类中的 this.listeners 属性中.

    1. 创建 EventPublishingRunListener

    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
        for (ApplicationListener<?> listener : application.getListeners()) {
            this.initialMulticaster.addApplicationListener(listener);
        }
    }

    1. 这里创建了一个多播器: SimpleApplicationEventMulticaster

      

     2. 将容器中10个监听器放入多播器中.

    上一篇提到过, 容器中加载了10个监听器, 放在 this.listeners 属性中.

      这里的顺序与配置的读取顺序不同, 是经过排序过的.

    addApplicationListener()
    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        synchronized (this.retrievalMutex) {
            // Explicitly remove target for a proxy, if registered already,
            // in order to avoid double invocations of the same listener.
            Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
            if (singletonTarget instanceof ApplicationListener) {
                this.defaultRetriever.applicationListeners.remove(singletonTarget);
            }
            this.defaultRetriever.applicationListeners.add(listener);
            this.retrieverCache.clear();
        }
    }
    ListenerRetriever 是 AbstractApplicationEventMulticaster 的一个内部类. 所以监听器是放在 一个内部类的 applicationListeners 属性中:
    public final Set<ApplicationListener<?>> applicationListeners;

    二. listeners.starting()

    public void starting() {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.starting();
        }
    }

    此处的 this.listeners 中的 this -> SpringApplicationRunListeners .

    所以调用的是 EventPublishingRunListener的starting() 方法.

    //EventPublishingRunListener.java
    @Override
    public void starting() {
       //创建Application的启动事件, 并进行多波
    this.initialMulticaster.multicastEvent( new ApplicationStartingEvent(this.application, this.args)); }

    看一下 multicastEvent 方法:

    //SimpleApplicationEventMulticaster.java
    @Override
    public void multicastEvent(ApplicationEvent event) {
        multicastEvent(event, resolveDefaultEventType(event));
    }
    
    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
      // getApplicationListeners 会对监听器进行过滤
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
         //获取线程池, 暂时为null Executor executor
    = getTaskExecutor(); if (executor != null) {
           //异步发送事件 executor.execute(()
    -> invokeListener(listener, event)); } else {
           //同步发送事件 invokeListener(listener, event); } } }
    getApplicationListeners()
    protected boolean supportsEvent(
            ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
    
        GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
                (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
        return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
    }

    1.  判断监听器是否为 GenericApplicationListener 类型

      |-> 如果是, 则调用其 supportsEventType() 和 supportsSourceType() , 且同时满足, 才可以. 否则会被过滤掉

      |-> 如果不是, 则 使用GenericApplicationListenerAdapter 进行适配转换, 然后 调用上面两个方法, 同时满足, 才可以. 否则会被过滤掉

    满足条件的有4个监听器:

     此处看一下 LoggingApplicationListener 的两个方法执行:

    1. supportsEventType()

    private static final Class<?>[] EVENT_TYPES = { ApplicationStartingEvent.class,
                ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class,
                ContextClosedEvent.class, ApplicationFailedEvent.class };
    
    @Override
    public boolean supportsEventType(ResolvableType resolvableType) {
        return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
    }
    
    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return isAssignableFrom(sourceType, SOURCE_TYPES);
    }
    
    private boolean isAssignableFrom(Class<?> type, Class<?>... supportedTypes) {
        if (type != null) {
            for (Class<?> supportedType : supportedTypes) {
                if (supportedType.isAssignableFrom(type)) {
                    return true;
                }
            }
        }
        return false;
    }

    可以看到, 这里他支持5中类型, 其中正好就有当前发布的 ApplicationStartingEvent 事件.

    2. supportsSourceType()

    private static final Class<?>[] SOURCE_TYPES = { SpringApplication.class,
                ApplicationContext.class };
    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
      //这里调用的还是上面的那个方法, 只是传入参数不同
    return isAssignableFrom(sourceType, SOURCE_TYPES); }
    invokeListener() 
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
      //不管 errorhandler 是否为null, 都会调用 doInvokeListener 方法 ErrorHandler errorHandler
    = getErrorHandler(); if (errorHandler != null) { try { doInvokeListener(listener, event); } catch (Throwable err) { errorHandler.handleError(err); } } else { doInvokeListener(listener, event); } } private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { listener.onApplicationEvent(event); } catch (ClassCastException ex) { String msg = ex.getMessage(); if (msg == null || matchesClassCastMessage(msg, event.getClass().getName())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for // -> let's suppress the exception and just log a debug message. Log logger = LogFactory.getLog(getClass()); if (logger.isDebugEnabled()) { logger.debug("Non-matching event type for listener: " + listener, ex); } } else { throw ex; } } }

    这里就是调用 监听器的  onApplicationEvent 方法, 并传入要多波的事件.

    这里仍然来看 LoggingApplicationListener 的 onApplicationEvent 方法:

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
      //Application启动
    if (event instanceof ApplicationStartingEvent) { onApplicationStartingEvent((ApplicationStartingEvent) event); }
      //环境准备完成
    else if (event instanceof ApplicationEnvironmentPreparedEvent) { onApplicationEnvironmentPreparedEvent( (ApplicationEnvironmentPreparedEvent) event); }
      //Application 准备完
    else if (event instanceof ApplicationPreparedEvent) { onApplicationPreparedEvent((ApplicationPreparedEvent) event); }
      //容器关闭
    else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event) .getApplicationContext().getParent() == null) { onContextClosedEvent(); }
      //Application启动失败
    else if (event instanceof ApplicationFailedEvent) { onApplicationFailedEvent(); } }

    不同的事件进来, 执行不同的方法. 

  • 相关阅读:
    用于.NET环境的时间测试(转)
    HTML->CSS->JS->PHP的顺序及相关网址(转)
    经典的CSS代码(转)
    初阶html学习总结(一)(转)
    如何学习javascript?(转)
    如何给网页标题栏上添加图标(favicon.ico)(转)
    网页颜色代码对照(转)
    前端开发代码命名的整理(转)
    前端代码规范总结(转)
    基于重心偏移的视差计算
  • 原文地址:https://www.cnblogs.com/elvinle/p/12341900.html
Copyright © 2011-2022 走看看