Take heart Springboot Source Analysis: two, SpringApplication.run () method on the part

Play ad

Personal write "springboot source analysis" of this series for a long time, but the lack of knowledge has been accumulated angle child's heart, it has not put pen to paper.

So I am looking to write this series of small partners, error correction mutual exchange of learning.

If there is little interested partners put together a series of words to explain the finish, plus my micro letter: 13670426148, we finish together, when the exchange of learning.

Late want to write a series of introductory rpc framework, but to another for a while, first springboot the finish, a more adhere to a week, weekend update

Foreword

Part recalled
talked SpringApplication instantiation, the most important is to load Spring's Listener and Initializer, Listener is 10, Initializer to 6, a detailed view take heart Springboot source code analysis: a, SpringApplication instantiation

After writing the articles found with the previous version springboot1.5, but now we are using springboot2. +, So I found a springboot2.0 + projects to be resolved, but it is not the first to change , and then when you are free to update, but the content is roughly about the same.

This mainly about run () method, divided into two parts, the upper part of this talk about, focused primarily run () method involved in an event - listeners - broadcasting system until create context portion (context = this.createApplicationContext ()).

run () method Method Overview

 public ConfigurableApplicationContext run(String... args) {
        //这是一个计时器,stopWatch.start()开始计时,到后面stopWatch.stop()停止计时。
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        //这个ConfigurableApplicationContext就是我们说的 上下文,后面preContext()的时候会详细解析,这个是springboot中最重要的一个类了
        ConfigurableApplicationContext context = null;
        //自定义SpringApplication启动错误的回调接口 
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        //此为设置 System 里面有一个properties的里的值 "java.awt.headless" ,设置为默认值true
        this.configureHeadlessProperty();
        //这个SpringApplicationRunListeners可跟前面的10个Listener不一样,这里面封装了一个广播。后面会讲他的实例化过程
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //开始进行事件广播,下面详细解析
        listeners.starting();
        Collection exceptionReporters;
        try {
            //获取初始化参数,就是我们运行时的初始化参数,比如“java -jar --port=8080” 其中port就是一个参数了   
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //environment是运行时环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            //打印出springboot的标志,这个可以自己选择要打印输出的文本.
            Banner printedBanner = this.printBanner(environment);
            //创建根上下文,这个方法特别重要,将是下章讲解的重点
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            //准备环境,下面先不讲了。
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

Broadcasting package

SpringApplicationRunListeners: SpringApplicationRunListener a set of storage, there are some methods mentioned will follow;

SpringApplicationRunListeners : 
    | SpringApplicationRunListener
        |SimpleApplicationEventMulticaster 
SimpleApplicationEventMulticaster
    才是真正的广播,SpringApplicationRunListeners只不过是对其的一层封装

Examples of process SpringApplicationRunListeners

private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
        //这里就不赘述了,META-INF/spring.factories下 
        //1. 获取key为SpringApplicationRunListener类路径为key 对应的 value
        //2. 实例化value对应的类,最后得到的类是EventPublishingRunListener.class,,如图1.1所示
        return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
    }

Figure 1.1:

So get SpringApplicationRunListeners which has an instance variable, the content is a EventPublishingRunListener consisting List .

  • EventPublishingRunListener inherited from SpringApplicationRunListener.
  • SpringApplicationRunListeners which has an instance variable, is composed of a plurality of EventPublishingRunListener List.

SpringApplicationRunListener structure

From the name, we know that it was a listener, that look at the entire startup process we will find that it is actually a listener to receive event notifications different enforcement points throughout the startup process, SpringApplicationRunListener Interface provides SpringBoot life cycle in the life cycle of each respective event broadcast, call the actual ApplicationListener class.
Next, look SpringApplicationRunListener
SpringApplicationRunListener Interface provides SpringBoot life cycle

public class SpringApplicationRunListener{
     //刚执行run方法时
    void started();
     //环境建立好时候
    void environmentPrepared(ConfigurableEnvironment environment);
     //上下文建立好的时候
    void contextPrepared(ConfigurableApplicationContext context);
    //上下文载入配置时候
    void contextLoaded(ConfigurableApplicationContext context);
    //上下文刷新完成后,run方法执行完之前
    void finished(ConfigurableApplicationContext context, Throwable exception);
}

It defines five steps:

  • started () -> run time execution method executed immediately; corresponding to the type of event is ApplicationStartedEvent, notification listener, SpringBoot started
  • environmentPrepared () -> Before ApplicationContext created and environmental information ready when you call; corresponding to the type of event is ApplicationEnvironmentPreparedEvent), notification listener, Environment ready
  • contextPrepared -> ApplicationContext created and called once before the source is loaded; there is no specific corresponding event), notification listener, ApplicationContext has been created and initialized completed
  • contextLoaded -> after ApplicationContext create and load and call before you refresh; corresponding to the type of event is ApplicationPreparedEvent), notification listener, ApplicationContext has completed IoC configuration value
  • finished -> call before the end of the run method; corresponding to the type of event is ApplicationReadyEvent or ApplicationFailedEvent), notification listener, SpringBoot start completion

EventPublishingRunListener constructor

We look EventPublishingRunListener constructor. And his two important ways:

EventPublishingRunListener class implements SpringApplicationRunListener, it has a function that broadcasts the event.

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    //这个是参数传进来的,也就是SpringApplication.class
    private final SpringApplication application;
    //这个是初始化参数
    private final String[] args;
    //真正的广 播
    private final SimpleApplicationEventMulticaster initialMulticaster;

    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
         //新建立广播器,这个广播器特别重要,下面继续解析
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
        //application.getListeners()就是获取10个初始化的Listenter,具体可以参见上一篇了解哪10个Listener
        Iterator var3 = application.getListeners().iterator();
        
        while(var3.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var3.next();
            //添加到内部的defaultRetriever里,详细代码可以自己翻进去查看,这里不拓展,
            //后面需要根据事件类型推测有哪些监听器需要被触发,所以就得存把所有的监听器先存起来,称作一个注册表吧
            this.initialMulticaster.addApplicationListener(listener);
        }

    }
}

That is, EventPublishingRunListener there are a broadcaster, in conjunction with the above SpringApplicationRunListener interface declares methods, we can get the mechanism is about:

  1. run () method is used to receive listener different enforcement points throughout the start of the event notification process, Wake listener
  2. And then go is to call EventPublishingRunListener the started (), environmentPrepared () such as wake-up, there will be different according to the method, started (), or environmentPrepared (), etc., to generate different events. Transmitted to the broadcaster.
  3. The broadcaster SimpleApplicationEventMulticaster initialMulticaster, then from the registry (the code above said formation of the registry is part of the code), depending on the type of Event and find those listeners need to be triggered, the implementation of its multicastEvent (ApplicationEvent event) method , the interior is invokeListener (listener, event);

Broadcaster

multicastEvent () method is a broadcast method
SimpleApplicationEventMulticaster broadcasted, broadcasted event object will be processed listeners property SpringApplication in.

First look at the following analytical method for broadcasting multicastEvent () and execute methods invokeListener ()


public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        //去注册表中根据相应的事件,获取Event对应的Listener。后面会简略讲讲获取的过程
        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);
            }
        }

    }
//执行方法
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = this.getErrorHandler();
        if (errorHandler != null) {
            try {
                //看多了源码你们会发现,spring的源码很喜欢这么写,一般invokeListener的时候不是真的invokeListener的真实过程
                //而是会把真正的逻辑放到 doInvokeListener(do****,这里就是doInvokeListener)中执行.
                 //1. 而在invokeListener中只是在真正处理方法前做一点数据封装,
                 //2. 或者异常检查
                 // 目的:个人感觉主要的目的是把真正处理过程的代码缩减,使得真正的处理逻辑变得简洁易懂,不会有多余的代码加重理解难度
                this.doInvokeListener(listener, event);
            } catch (Throwable var5) {
                errorHandler.handleError(var5);
            }
        } else {
            this.doInvokeListener(listener, event);
        }
    }    
    
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
        //这里就很明白了,执行监听器的方法
            listener.onApplicationEvent(event);
        } catch (ClassCastException var6) {
            String msg = var6.getMessage();
            if (msg != null && !this.matchesClassCastMessage(msg, event.getClass())) {
                throw var6;
            }

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

So to sum up
two on duration and broadcaster relationship is as follows:
SpringApplicationRunListeners, SpringApplicationRunListener, SimpleApplicationEventMulticaster

(1) SpringApplicationRunListeners is SpringApplicationRunListener package. pringApplicationRunListeners SpringApplicationRunListener contains a plurality,
in order to perform the bulk package, the same SpringApplicationRunListeners SpringApplicationRunListener life cycle, each cycle SpringApplicationRunListener each call
and broadcast using a broadcast SimpleApplicationEventMulticaster.

(2) SimpleApplicationEventMulticaster SpringApplicationRunListener is encapsulated inside the broadcaster,

SpringApplicationRunListener can be seen by the above three characteristics. springboot start listening notice several major correction process is carried out by him.
1.2 flowchart shown in FIG.


Where we can see the relationship between them.

He began running the first event started

The code directly see listeners.starting()this line

class SpringApplicationRunListeners {
     public void starting() {
        //这里获取SpringApplicationRunListeners里面的List<SpringApplicationRunListener> 
        Iterator var1 = this.listeners.iterator();
        //一般情况下,他只是一个,虽然这里是个list,所以这个while里面只会走1次
        while(var1.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
            //这个就进去到SpringApplicationRunListener里面去了,而此时SpringApplicationRunListener的实现类是EventPublishingRunListener
            listener.starting();
        }
    }
}
/**
**  EventPublishingRunListener实现了SpringApplicationRunListener,所以就得实现里面的starting(), environmentPrepared()等,贯穿整个springboot启动流程,而starting()只是他其中最开始的一步,看最上面整体的代码部分就知道了,后面还有environmentPrepared(), contextPrepared()等
**/
pubic class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    
    public void starting() {
        //1. 广播器执行广播事件方法
        //2. 参数是包装出来的 ApplicationStartingEvent ,跟下面的environmentPrepared,contextPrepared方法比,他们的事件都类型都不同的
       
        //(1) starting对应的是ApplicationStartingEvent
        //(2) environmentPrepared对应的是 ApplicationEnvironmentPreparedEvent
        //(3) ApplicationContextInitializedEvent对应的是 ApplicationContextInitializedEvent
        this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
    }
    
     public void environmentPrepared(ConfigurableEnvironment environment) {
        this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
    }

    public void contextPrepared(ConfigurableApplicationContext context) {
        this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
    }
    
    //省略****
}


public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {   
    //开始进行广播方法,因为此时是staring()方法出发的,所以这里的envent是在EventPublishingRunListener中new ApplicationContextInitializedEvent,
    public void multicastEvent(ApplicationEvent event) {
        //1. 第二个参数推断出eventType,,在真正执行广播
        this.multicastEvent(event, this.resolveDefaultEventType(event));
    }
    
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {   //推断出类型
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        //从注册表中根据event类型,获得所有对应的监听器,
        //结果获得的所有监听器有:
        //(1) LoggingApplicationListener、
        //(2) BackgroundPreinitializer、
        //(3) DelegatingApplicationListener
        //(4) LiquibaseServiceLocatorApplicationListener
        //(5)EnableEncryptablePropertiesBeanFactoryPostProcessor
        //五种类型的对象。这五个对象的onApplicationEvent都会被调用。
        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);
            }
        }
    }
//这就是最终的调用点,Listener的onApplicationEvent(ApplicationEvent) 方法。
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);
        } catch (ClassCastException var6) {
            String msg = var6.getMessage();
            if (msg != null && !this.matchesClassCastMessage(msg, event.getClass())) {
                throw var6;
            }

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

So the five listeners onApplicationEvent have done, and I probably say here, the details, then all of you to talk to the source code.

(1) LoggingApplicationListener: log system initialization, the default is logback, supports three, highest to lowest priority: logback> log4j> javalog

(2) BackgroundPreinitializer: Start a respective plurality of threads of execution of tasks, including verification, a message converters, etc.

(3) DelegatingApplicationListener: did not do anything at this time

(4) LiquibaseServiceLocatorApplicationListener:此时什么也没做

(5)EnableEncryptablePropertiesBeanFactoryPostProcessor:仅仅打印了一句日志,其他什么也没做
对了,补充一点注册器的代码
喜欢就看,不喜欢就跳过,

// 返回所有的适合于ApplicationStartedEvent的监听器集合
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
        Object source = event.getSource();
        Class<?> sourceType = source != null ? source.getClass() : null;
        //根据eventType和sourceType组装一个key即是cacheKey
        AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
        //retriever里面包装了所有适合的监听器。
        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))) {
            synchronized(this.retrievalMutex) {
                retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
                if (retriever != null) {
                    return retriever.getApplicationListeners();
                } else {
                    //当第一次执行的时候,创建一个 retriever,
                    retriever = new AbstractApplicationEventMulticaster.ListenerRetriever(true);
                    //下面进行详细解析;
                    //直接在这里获取所有适合于ApplicationStartedEvent的监听器集合,并使用retriever.applicationListeners.add(listener);,添加到retriever中, 
                    Collection<ApplicationListener<?>> listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever);
                    //以cacheKey为key,存到缓存中。
                    this.retrieverCache.put(cacheKey, retriever);
                    //返回所有的适合于ApplicationStartedEvent的监听器集合
                    return listeners;
                }
            }
        } else {
            return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null);
        }
    }

//上面方法的解析,直接在这里获取所有适合于ApplicationStartedEvent的监听器集合。
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable 
                                                                        AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
        List<ApplicationListener<?>> allListeners = new ArrayList();
        LinkedHashSet listeners;
        LinkedHashSet listenerBeans;
        synchronized(this.retrievalMutex) {
            //this.defaultRetriever.applicationListeners是所有默认的监听器,就是那10个默认的监听器,如下图所示
            listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
            listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
        }
        
        Iterator var7 = listeners.iterator();

        while(var7.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var7.next();
            //就是在这里进行判断的,具体怎么判断就不进去了,这个不是重点
            if (this.supportsEvent(listener, eventType, sourceType)) {
                if (retriever != null) {
                    retriever.applicationListeners.add(listener);
                }

                allListeners.add(listener);
            }
        }
    
    //........篇幅有限,这个其实不重要,直接略过即可
}

准备环境 prepareEnvironment

//todo: 这部分可以用“监听器-事件-广播” 解释一下,下周末有时间再进行补充。
prepareEnvironment(listeners, applicationArguments);

 加载SpringBoot配置环境(configurableEnvironment),如果是通过web容器发布,会加载StandardEnvironment。将配置文件(Environment)加入到监听器对象中(SpringApplicationRunListeners)

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments) {
    // Create and configure the environment
    //如果environment不为空直接返回 || 如果是web环境则直接实例化StandardServletEnvironment类 || 如果不是web环境则直接实例化StandardEnvironment类
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    //配置环境信息
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    //通知所有的监听者,环境已经准备好了
    listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
                deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

总结

本篇主要讲了“监听器-事件-广播”的涉及到的几个类,展示了一个周期 starting()的运行过程。
再总结一下,流程如下:

  1. run()方法是用来在整个启动流程中接收不同执行点事件通知的监听者,唤醒监听者
  2. 而再进去就是调用EventPublishingRunListener的started()、environmentPrepared()等唤醒的,这里面就会有根据不同的方法,started(),或者environmentPrepared()等,生成不同的事件。传递给广播器。
  3. 而广播器SimpleApplicationEventMulticaster initialMulticaster, 就从注册表中(上文代码说了注册表的形成是那段代码),根据Event的类型,找到那些监听器是需要被触发的,执行其 multicastEvent(ApplicationEvent event) 方法,内部是invokeListener(listener, event);

    下期预告

    下期打算讲一讲, context的部分,这个内容就有很多了啊。。

参考内容: 大神写的,分析很透彻,站在巨人的肩膀上:

http://www.mamicode.com/info-detail-2735609.html

https://cloud.tencent.com/developer/article/1333056

Guess you like

Origin www.cnblogs.com/disandafeier/p/12081290.html