VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • srpingboot web - 启动(3) 监听器

一. 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();
    }
}
复制代码

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


相关教程