Springboot启动流程(二):listener的启动

Springboot启动流程(二)
之前我们看了Application的赋值流程,之后的run方法调用才是启动流程的重点:
run方法代码如下:
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
                applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        exceptionReporters = getSpringFactoriesInstances(
                SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, context);
        prepareContext(context, environment, listeners, applicationArguments,
                printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                    .logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }

    try {
        listeners.running(context);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}
try 之前的代码是获取和执行listeners的,同样调用了getSpringFactoriesInstances方法获取的对象,代码:
private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class[] types = new Class[] { SpringApplication.class, String[].class };
    return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
            SpringApplicationRunListener.class, types, this, args));
}
获取了SpringApplicationRunListener的对象数组并且放入SpringApplicationRunListeners中.之后调用starting方法开启全部listener:
SpringApplicationRunListeners 类:
public void starting() {
    for (SpringApplicationRunListener listener : this.listeners) {
        listener.starting();
    }
}
调用了EventPublishingRunListener的starting方法,我们来看下具体代码:
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);
    }
}

@Override
public void starting() {
    this.initialMulticaster.multicastEvent(
            new ApplicationStartingEvent(this.application, this.args));
}
首先是调用构造方法为initialMulticaster赋值,然后把application.getListeners()获得的所有listener加到initialMulticaster中,
application的listener的获取方法在之前获取SpringApplication对象时已经获取过了.
addApplicationListener 方法:
AbstractApplicationEventMulticaster 类:
@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();
    }
}
以上代码首先去除了所有实现了aop的listener对象,然后把listener放入defaultRetriever的applicationListeners中,最后清除缓存
defaultRetriever是AbstractApplicationEventMulticaster的内部类,他主要是囊括了特定的listener来有效的搜寻listeners
/**
 * Helper class that encapsulates a specific set of target listeners,
 * allowing for efficient retrieval of pre-filtered listeners.
 *

An instance of this helper gets cached per event type and source type.
 */
为什么要去除实现了aop的对象?
上面的注释解释了原因:为了避免多次调用一个listener!
在一系列的出事话event操作后,开始真正的处理listener:
new 了一个ApplicationStartingEvent对象并把它放入initialMulticaster的multicastEvent中.
SimpleApplicationEventMulticaster 中的multicastEvent方法:
@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));
    for (final ApplicationListener listener : getApplicationListeners(event, type)) {
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}
从上面的代码可以初步分析出他是用来调用listener的方法.
首先调用resolveDefaultEventType方法处理event,这个resolveDefaultEventType是干什么的呢?
resolveDefaultEventType:
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
    return ResolvableType.forInstance(event);
}
他直接调用了ResolvableType.forInstance(event)方法:
ResolvableType 类:
public static ResolvableType forInstance(Object instance) {
    Assert.notNull(instance, "Instance must not be null");
    if (instance instanceof ResolvableTypeProvider) {
        ResolvableType type = ((ResolvableTypeProvider) instance).getResolvableType();
        if (type != null) {
            return type;
        }
    }
    return ResolvableType.forClass(instance.getClass());
}
如果instance实现了ResolvableTypeProvider接口则使用ResolvableTypeProvider.getResolvableType方法获取type,否则使用forClass方法获取,
ResolvableTypeProvider.getResolvableType调用了forClassWithGenerics方法并传入通过playload获取的ResolvableType对象
具体意思就是如果实现了ResolvableTypeProvider接口则返回带属性type的ResolvableType对象否则返回不带属性的对象
获取完eventType后开始处理listeners
protected Collection> getApplicationListeners(
        ApplicationEvent event, ResolvableType eventType) {

    Object source = event.getSource();
    Class sourceType = (source != null ? source.getClass() : null);
    ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

    // Quick check for existing entry on ConcurrentHashMap...
    ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
    if (retriever != null) {
        return retriever.getApplicationListeners();
    }

    if (this.beanClassLoader == null ||
            (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
                    (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
        // Fully synchronized building and caching of a ListenerRetriever
        synchronized (this.retrievalMutex) {
            retriever = this.retrieverCache.get(cacheKey);
            if (retriever != null) {
                return retriever.getApplicationListeners();
            }
            retriever = new ListenerRetriever(true);
            Collection> listeners =
                    retrieveApplicationListeners(eventType, sourceType, retriever);
            this.retrieverCache.put(cacheKey, retriever);
            return listeners;
        }
    }
    else {
        // No ListenerRetriever caching -> no synchronization necessary
        return retrieveApplicationListeners(eventType, sourceType, null);
    }
}
调用了getApplicationListeners方法:
首先第一个问题:
Object source = event.getSource();获取的object是什么?
我们回来看starting的代码:
@Override
public void starting() {
    this.initialMulticaster.multicastEvent(
            new ApplicationStartingEvent(this.application, this.args));
}
他new了一个ApplicationStartingEvent对象,其构造方法调用了super();构造了一个SpringApplicationEvent对象,SpringApplicationEvent的构造方法
又调用了super构造了ApplicationEvent的抽象类,这个抽象类是继承EventObject类的,而EventObject的构造方法把传入的resouce存入对象中,所以
event.getSource();方法获取的是一开始传入的application对象,既创建对象时传入的this:SpringApplication对象!
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
                SpringApplicationRunListener.class, types, this, args));
接下来包装了一个缓存的key并且使用这个key获取ListenerRetriever对象,但我们是第一次调用所以要接着向下走
if (this.beanClassLoader == null ||
                (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
                        (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))))
beanClassLoader没有被赋值所以会进入这个if中处理:
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
    return retriever.getApplicationListeners();
}
首先在判断下缓存中有没有防止缓存击穿,然后创建ListenerRetriever的对象,然后通过retrieveApplicationListeners方法搜寻listenser:
private Collection> retrieveApplicationListeners(
        ResolvableType eventType, @Nullable Class sourceType, @Nullable ListenerRetriever retriever) {

    List> allListeners = new ArrayList<>();
    Set> listeners;
    Set listenerBeans;
    synchronized (this.retrievalMutex) {
        listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
        listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
    }
    for (ApplicationListener listener : listeners) {
        if (supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
                retriever.applicationListeners.add(listener);
            }
            allListeners.add(listener);
        }
    }
    if (!listenerBeans.isEmpty()) {
        BeanFactory beanFactory = getBeanFactory();
        for (String listenerBeanName : listenerBeans) {
            try {
                Class listenerType = beanFactory.getType(listenerBeanName);
                if (listenerType == null || supportsEvent(listenerType, eventType)) {
                    ApplicationListener listener =
                            beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
                        if (retriever != null) {
                            if (beanFactory.isSingleton(listenerBeanName)) {
                                retriever.applicationListeners.add(listener);
                            }
                            else {
                                retriever.applicationListenerBeans.add(listenerBeanName);
                            }
                        }
                        allListeners.add(listener);
                    }
                }
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Singleton listener instance (without backing bean definition) disappeared -
                // probably in the middle of the destruction phase
            }
        }
    }
    AnnotationAwareOrderComparator.sort(allListeners);
    if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
        retriever.applicationListeners.clear();
        retriever.applicationListeners.addAll(allListeners);
    }
    return allListeners
}
首先把defaultRetriever中的listener加入listeners,defaultRetriever中的listener是在EventPublishingRunListener中的构造方法中赋值上文已经
研究过了,因为暂时没有赋值applicationListenerBeans所以listenerBeans的size为0
然后判断listener是否支持eventtype和sourcetype,如果支持则加入retriever的applicationListeners中并把listener加入allListeners中返回.
回到getApplicationListeners方法中,把new的retriever放入缓存中并放回listeners.
之后返回到 SimpleApplicationEventMulticaster 类的multicastEvent方法中,获取了所有listener后获取taskExecutor因为获取的executor是空的,所以
执行invokeListener(listener, event)方法调用各种listener的onApplicationEvent方法执行具体代码.
以上就是listener的的运行流程,需要考虑的问题有几个:
1.getApplicationListeners中获取的是Collection>如何保证retriever获取的一定是实现ApplicationListener的对象?
这个问题产生是我的一个误区,我看到getRunListeners中获取的是SpringApplicationRunListener的对象下意识的一位后面所有用的都是这个对象,但其实
在后面只是在条用starting的时候用到这个对象,其他对象都是在EventPublishingRunListener的构造中this.initialMulticaster.addApplicationListener(listener)
方法中获取的,而这个listener是application.getListeners的集合中的元素,在前面研究的初始化流程中通过setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
赋值,确实是ApplicationListener的对象.
总结来说SpringApplicationRunListeners并不是具体的listener,而是包装了启动所需要的listener的一个类.
2.这一块儿代码最核心的设计模式是什么?
观察者模式.(定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.)

你可能感兴趣的:(代码)