美文网首页
Springboot源码跟读2--SpringApplicati

Springboot源码跟读2--SpringApplicati

作者: 安中古天乐 | 来源:发表于2020-04-15 20:46 被阅读0次

上一篇我们讲了SpringApplication的创建,这1篇开始讲SpringApplication的run方法:

胖子不是一口吃出来的,我们一步步来,先看部分代码:

public ConfigurableApplicationContext run(String... args) {
    // 创建时钟(主要用于记录运行时间等信息)
    StopWatch stopWatch = new StopWatch();
    // 开启时钟
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    this.configureHeadlessProperty();
    // 获取ClassPath下的SpringApplicationRunListener实现类集合
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    // 遍历SpringApplicationRunListener实现类集合,逐个执行starting()方法
    listeners.starting();
    ...
}

解析getRunListeners方法之前,先看看SpringApplicationRunListener是个啥东东。

public interface SpringApplicationRunListener {
    void starting();

    void environmentPrepared(ConfigurableEnvironment environment);

    void contextPrepared(ConfigurableApplicationContext context);

    void contextLoaded(ConfigurableApplicationContext context);

    void started(ConfigurableApplicationContext context);

    void running(ConfigurableApplicationContext context);

    void failed(ConfigurableApplicationContext context, Throwable exception);
}

很简单,就是个接口,定义了7个方法,分别对应了SpringApplication启动的各个阶段。

当SpringApplication运行到某个阶段时,则回调各接口继承类实例该阶段对应的方法。

接着看getRunListeners方法:

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

又看到了熟悉的getSpringFactoriesInstances方法,其目的是扫描ClassPath下所有的"META-INF/spring.factories",拿到SpringApplicationRunListener的各继承类的Class Name,然后基于反射创建各继承类的实例返回。

接着看listeners.starting():

public void starting() {
    Iterator var1 = this.listeners.iterator();

    while(var1.hasNext()) {
        SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
        listener.starting();
    }

}

就是个遍历listeners,然后调用每个SpringApplicationRunListener元素的starting()方法。

到此,即完成了SpringApplicationRunListener的加载及starting。

哈哈,是不是很简单,我们实践一波。

建一个空的Springboot Web项目,设置断点,Debug一下:

1.jpg 2.jpg

可以看到,仅有1个SpringApplicationRunListener继承类被加载,即EventPublishingRunListener。

首先,看下它的构造函数:

public EventPublishingRunListener(SpringApplication application, String[] args) {
    this.application = application;
    this.args = args;
    this.initialMulticaster = new SimpleApplicationEventMulticaster();
    Iterator var3 = application.getListeners().iterator();

    while(var3.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var3.next();
        this.initialMulticaster.addApplicationListener(listener);
    }

}

主要将SpringApplication创建时初始化的ApplicationListener集合赋给EventPublishingRunListener的initialMulticaster字段。

initialMulticaster.addApplicationListener方法,可以看到ApplicationListener最终被add进了ApplicationEventMulticaster的defaultRetriever.applicationListeners。

public void addApplicationListener(ApplicationListener<?> listener) {
    Object var2 = this.retrievalMutex;
    synchronized(this.retrievalMutex) {
        Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
        if (singletonTarget instanceof ApplicationListener) {
            this.defaultRetriever.applicationListeners.remove(singletonTarget);
        }

        this.defaultRetriever.applicationListeners.add(listener);
        this.retrieverCache.clear();
    }
}

applicationListeners是defaultRetriever中ApplicationListener的Set。

private class ListenerRetriever {
    public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet();
    public final Set<String> applicationListenerBeans = new LinkedHashSet();
    private final boolean preFiltered;
    ...
}

Debug一下:

3.jpg

所以,EventPublishingRunListener创建后,其持有了SpringApplication创建时初始化的ApplicationListener继承类实例集合。

接着看EventPublishingRunListener的starting()方法实现:

public void starting() {
    this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}

首先,基于传入的SpringApplication实例和args,构建ApplicationStartingEvent传给initialMulticaster的multicastEvent方法。

public void multicastEvent(ApplicationEvent event) {
    this.multicastEvent(event, this.resolveDefaultEventType(event));
}

public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
    Iterator var4 = this.getApplicationListeners(event, type).iterator();

    while(var4.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var4.next();
        Executor executor = this.getTaskExecutor();
        if (executor != null) {
            executor.execute(() -> {
                this.invokeListener(listener, event);
            });
        } else {
            this.invokeListener(listener, event);
        }
    }

}

初步看就是根据event及其eventType调用getApplicationListeners(event, type)方法完成ApplicationListener的筛选。

遍历筛选后的ApplicationListener,根据event调用具体的事件方法,完成事件的发布。

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    ErrorHandler errorHandler = this.getErrorHandler();
    if (errorHandler != null) {
        try {
            this.doInvokeListener(listener, event);
        } catch (Throwable var5) {
            errorHandler.handleError(var5);
        }
    } else {
        // 实际调用doInvokeListener
        this.doInvokeListener(listener, event);
    }
}

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    try {
        // 传入事件,调用ApplicationListener的onApplicationEvent方法,完成事件发布
        listener.onApplicationEvent(event);
    } catch (ClassCastException var6) {
        String msg = var6.getMessage();
        if (msg != null && !this.matchesClassCastMessage(msg, event.getClass().getName())) {
            throw var6;
        }

        Log logger = LogFactory.getLog(this.getClass());
        if (logger.isDebugEnabled()) {
            logger.debug("Non-matching event type for listener: " + listener, var6);
        }
    }

}

先看getApplicationListeners方法:

protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
    Object source = event.getSource();
    Class<?> sourceType = source != null ? source.getClass() : null;
    AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
    AbstractApplicationEventMulticaster.ListenerRetriever retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
    if (retriever != null) {
        return retriever.getApplicationListeners();
    } else if (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) {
        Object var7 = this.retrievalMutex;
        synchronized(this.retrievalMutex) {
            retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
            if (retriever != null) {
                return retriever.getApplicationListeners();
            } else {
                retriever = new AbstractApplicationEventMulticaster.ListenerRetriever(true);
                Collection<ApplicationListener<?>> listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever);
                this.retrieverCache.put(cacheKey, retriever);
                return listeners;
            }
        }
    } else {
        return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null);
    }
}

首先根据eventType, sourceType构建cacheKey,然后根据cacheKey尝试从缓存中取出retriever,若retriever不为null,则直接返回retriever.getApplicationListeners(),否则通过retrieveApplicationListeners返回listeners,并更新缓存。

继续看一下retrieveApplicationListeners方法:

private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
    LinkedList<ApplicationListener<?>> allListeners = new LinkedList();
    Object var7 = this.retrievalMutex;
    LinkedHashSet listeners;
    LinkedHashSet listenerBeans;
    synchronized(this.retrievalMutex) {
        // 拿到EventPublishingRunListener持有的ApplicationListener实例集合
        // 也是SpringApplication创建时初始化的ApplicationListener实例集合
        listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
        listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
    }

    Iterator var14 = listeners.iterator();

    while(var14.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var14.next();
        // 调用supportsEvent为True
        // 则将该ApplicationListener添加进retriever的applicationListeners中
        if (this.supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
                retriever.applicationListeners.add(listener);
            }

            allListeners.add(listener);
        }
    }
    
    // 如果listenerBeans不为空,则通过beanFactory的getBean方法获取前面allListeners不包含且supportsEvent为True的ApplicationListener
    // 将其添加进retriever的applicationListeners中
    if (!listenerBeans.isEmpty()) {
        BeanFactory beanFactory = this.getBeanFactory();
        Iterator var16 = listenerBeans.iterator();

        while(var16.hasNext()) {
            String listenerBeanName = (String)var16.next();

            try {
                Class<?> listenerType = beanFactory.getType(listenerBeanName);
                if (listenerType == null || this.supportsEvent(listenerType, eventType)) {
                    ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) {
                        if (retriever != null) {
                            retriever.applicationListenerBeans.add(listenerBeanName);
                        }

                        allListeners.add(listener);
                    }
                }
            } catch (NoSuchBeanDefinitionException var13) {
                ;
            }
        }
    }
    // 根据@Value注解排序
    AnnotationAwareOrderComparator.sort(allListeners);
    return allListeners;
}

关键在于supportsEvent方法:

protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
    GenericApplicationListener smartListener = listener instanceof GenericApplicationListener ? (GenericApplicationListener)listener : new GenericApplicationListenerAdapter(listener);
    return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType);
}

先将传入的ApplicationListener转成GenericApplicationListener,然后依次调用supportsEventType和supportsSourceType方法,若均返回True,则该方法返回True。

至此,SpringApplicationRunListener的加载及starting源码跟读完毕。

相关文章

网友评论

      本文标题:Springboot源码跟读2--SpringApplicati

      本文链接:https://www.haomeiwen.com/subject/xhwhvhtx.html