春ブーツSpringApplication開始クラス(B)

序文

        私たちはここにあると私たちは、記事を探索する探索したり、汚染されたサプリメントを持っていると同時に、後で簡単に呼び出すためのダウンノートの形での学習春ブーツの間に記録された最近の関連コースは、誤った希望を、我々は速やかに上げることができ、私は事前にあなたに感謝します!

あなたはそれを開始する前に、私はいくつかの質問に学ぶことを願っています:
1.どのような春ブーツSpringApplicationこと?
2、プロセス全体の構造または何?
3.キー要素またはコア部分は何ですか?
4、どのように達成するために?
図5は、春が関連付けどのようにしているのですか?
それは私が、学ぶことの問題は、学ぶための良い方法だと思う理解するために貢献し、自己の問題です。さて、その後、テーマに。

1、起源

        前回の記事では、私たちの話SpringApplication、この段階では、準備段階のような準備に必要なランタイム・リソースを、完了:initializerslistenersというように。そして、この記事では、我々はについて何か言うだろうSpringApplication、この段階では、それが起動する方法です、運用段階のSpringアプリケーションコンテキストを、とする方法Springイベントを組み合わせて、完全な形SpringApplicationのライフサイクルを。

注:この記事は、使用されているSpring Bootバージョンを2.1.6.BUILD-SNAPSHOT

2、SpringApplication運用段階

        前回の記事では、私たちの話SpringApplication、我々はについて何か言っているここでは、工法SpringApplication、次のように、メソッドを実行しているコアを、:

public class SpringApplication {

    ...
        
    public ConfigurableApplicationContext run(String... args) {
        // 这是 Spring 的一个计时器,计算代码的执行时间(ms级别)
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        // 这俩变量在后面赋值处进行说明
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        
        // 用来设置java.awt.headless属性值
        configureHeadlessProperty();
        
        // 该对象属于组合模式的实现,核心是内部关联的 SpringApplicationRunListener 集合,SpringApplicationRunListener 是 Spring Boot 的运行时监听器
        SpringApplicationRunListeners listeners = getRunListeners(args);
        // 会在不同的阶段调用对应的方法,这里表示启动run方法被调用
        listeners.starting();
        
        try {
        
            // 用来获取 SpringApplication.run(args)传入的参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            
            // 获取 properties 配置文件
            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            
            // 设置 spring.beaninfo.ignore 的属性值,判断是否跳过搜索BeanInfo类
            configureIgnoreBeanInfo(environment);
            
            // 这里是项目启动时,控制台打印的 Banner
            Banner printedBanner = printBanner(environment);
            
            // 这里就是创建 Spring 应用上下文
            context = createApplicationContext();
            
            // 获取 spring.factories 中key为 SpringBootExceptionReporter 的类名集合
            exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
                    
            // 这里是准备 Spring 应用上下文
            prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            
            // 这里是启动 Spring 应用上下文,底层调用的是 ApplicationContext 的 refresh() 方法,到这里就正式进入了 Spring 的生命周期,同时,SpringBoot的自动装配特性也随之启动
            refreshContext(context);
            
            // 里面是空的,猜测应该是交由开发人员自行扩展
            afterRefresh(context, applicationArguments);
            stopWatch.stop();
            
            // 这里打印启动信息
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
            }
            
            // ApplicationContext 启动时,调用该方法
            listeners.started(context);
            
            // 项目启动后,做的一些操作,开发人员可自行扩展
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }
    
        try {
        
            // ApplicationContext 启动完成时,调用该方法
            listeners.running(context);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }
    
    ...
}

上記のプロセス全体の概要を説明し、あなたはそれが混沌と見えますが、より多くの操作は、運用段階で行われるが、実際には従うべきルールがある見ることができます。例えば、実行SpringApplicationRunListenersだけ起動相相法はstarting、始動段階であったstarted完了の段階を開始する、runningというように。ならびに対応するSpringアプリケーション・コンテキストは、動作を開始する準備が作成されます。次に、議論のためのいくつかの中核主題の内側にあります。

2.1 SpringApplicationRunListeners構造

で見てみましょうSpringApplicationRunListenersオブジェクト、オブジェクトがして、コードから見ることができますgetRunListeners作成方法:

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

それは、渡すことで見ることができgetSpringFactoriesInstances、戻り値を、実装のSpringApplicationRunListenersコンストラクタは、オブジェクトを作成しました。そして、見てgetSpringFactoriesInstancesのメソッドを:

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = getClassLoader();
    // Use names and ensure unique to protect against duplicates
    Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

私たちは私たちが知っている、以前の記事、この方法を議論することで、よりよく理解しておく必要があり、これを参照してくださいSpringFactoriesLoader.loadFactoryNamesすべてのclasspass下のリターンをspring.factoriesで重要な文書としてSpringApplicationRunListenerコレクション実装クラス。春ブーツとして内蔵の実装:

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

最後に、入ってくるのコレクションがありSpringApplicationRunListenersコンストラクタは:

class SpringApplicationRunListeners {

    ...

    private final List<SpringApplicationRunListener> listeners;

    SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
        this.log = log;
        this.listeners = new ArrayList<>(listeners);
    }

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

    ...

}

セットに割り当てられるlisteners見られる属性SpringApplicationRunListenersモードの組み合わせで実装、コアが実際に内部に関連付けられているSpringApplicationRunListener外部の呼び出しプロセスのこの段階では、セットが繰り返し実行されるオブジェクトの集合、SpringApplicationRunListenerメソッドに対応します。それでは、私たちは議論する必要がありSpringApplicationRunListener

2.1.1 SpringApplicationRunListenerイベントとリスナーの仕組み

SpringApplicationRunListener担当SpringBoot対応する放送イベントの異なる段階、その後、実際の呼び出しApplicationListenerクラスで、クラスのonApplicationEventに応じて、方法Spring Boot、対応するアクションイベントの実施。全体のプロセスは、おそらくそう、その後、詳細に検討すること、で見てみましょうSpringApplicationRunListener定義:

public interface SpringApplicationRunListener {

    // 在run()方法开始执行时被调用,表示应用刚刚启动,对应的 Spring Boot 事件为 ApplicationStartingEvent
    void starting();

    // ConfigurableEnvironment 构建完成时调用,对应的 Spring Boot 事件为 ApplicationEnvironmentPreparedEvent
    void environmentPrepared(ConfigurableEnvironment environment);

    // ApplicationContext 构建完成时调用,对应的 Spring Boot 事件为 ApplicationContextInitializedEvent
    void contextPrepared(ConfigurableApplicationContext context);

    // ApplicationContext 完成加载但还未启动时调用,对应的 Spring Boot 事件为 ApplicationPreparedEvent
    void contextLoaded(ConfigurableApplicationContext context);

    // ApplicationContext 已启动,但 callRunners 还未执行时调用,对应的 Spring Boot 事件为 ApplicationStartedEvent
    void started(ConfigurableApplicationContext context);

    // ApplicationContext 启动完毕被调用,对应的 Spring Boot 事件为 ApplicationReadyEvent
    void running(ConfigurableApplicationContext context);

    // 应用出错时被调用,对应的 Spring Boot 事件为 ApplicationFailedEvent
    void failed(ConfigurableApplicationContext context, Throwable exception);

}

上にロードされ、その実装クラス、で見てみましょうspring.factoriesファイルEventPublishingRunListenerもクラスSpring Boot次のようにのみ実装クラスを構築し、クラスでイベントをブロードキャストする具体的な操作は、コードは次のとおりです。

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {

    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();
        for (ApplicationListener<?> listener : application.getListeners()) {
            this.initialMulticaster.addApplicationListener(listener);
        }
    }

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

    ...

}

これは、コンストラクタで作成された見ることができますEventPublishingRunListener呼び出して、インスタンスのgetListeners方法、SpringApplicationすべてのApplicationListenerリスナーにリンクされているinitialMulticasterプロパティを。はい、ここだApplicationListenerリスナーはで最後の記事ですSpringApplicationから、準備段階spring.factoriesにロードされたファイルのキーApplicationListener実装クラスのコレクション、上書きすべての実装クラスの収集onApplicationEvent方法。

2.1.2 SimpleApplicationEventMulticaster放送

ここで再び別のカテゴリにつながりSimpleApplicationEventMulticasterクラスがあり、Spring様々なイベントにそれを介してブロードキャストされるイベントの放送局、。外部反復実行する際に続いて、EventPublishingRunListenerstartingタイム法を、によるであろうイベントを放送する方法であって、ここではそれが放送されているイベントは、我々は、入力方法を:SimpleApplicationEventMulticastermulticastEventApplicationStartingEventmulticastEvent

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    ...
    
    @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));
        Executor executor = getTaskExecutor();
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            }
            else {
                invokeListener(listener, event);
            }
        }
    }
}

getApplicationListeners方法、関連上部から返されたイベントの種類に応じてApplicationListenerマッチングの組外フィルタApplicationListenerによれば、一連のSpring Bootこの段階で得られたバージョン、またなどの異なるリスナーとすることができる2.1.6.BUILD-SNAPSHOTバージョン戻り:
画像

次に、これらのリスナーを横断、同期または非同期呼び出しinvokeListener方法を:

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        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())) {
                // 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.isTraceEnabled()) {
                    logger.trace("Non-matching event type for listener: " + listener, ex);
                }
            }
            else {
                throw ex;
            }
        }
    }

あなたは、その最後の呼び出し見ることができるdoInvokeListener方法で実行される方法、ApplicationListeneronApplicationEventイベントオブジェクトの放送のための上院へのアプローチを。私たちは、リスナーの1人のを見ていたonApplicationEvent、そのようなの実現にBackgroundPreinitializerクラス:

public class BackgroundPreinitializer implements ApplicationListener<SpringApplicationEvent> {

    ...
    
    @Override
    public void onApplicationEvent(SpringApplicationEvent event) {
        if (!Boolean.getBoolean(IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME)
                && event instanceof ApplicationStartingEvent && preinitializationStarted.compareAndSet(false, true)) {
            performPreinitialization();
        }
        if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent)
                && preinitializationStarted.get()) {
            try {
                preinitializationComplete.await();
            }
            catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    ...
}

この方法では、instanceofイベントの種類の決意は、それによって対応する動作を行います。リスナーの主な動作は、コンバータをメッセージング、認証を含むこれらの初期の時間のかかる作業を実行するバックグラウンドスレッドを作成することです。LoggingApplicationListenerリスナーがあるSpring Bootいくつかの事前操作を行うには、ログシステム初期化。この段階で、さらに2つのリスナーノーオペレーション。

これまでのところ、SpringBootイベントメカニズムの全体的な流れは、おそらくので、我々は簡単にいくつかのコア・コンポーネントを確認します。

  • SpringApplicationRunListeners:でまず、runクラスのメソッドの実装の方法により、SpringBoot単に通話の開始段階のように、方法の異なる段階の異なる段階を呼び出すstarting方法。

  • SpringApplicationRunListenerは:とSpringApplicationRunListeners内部それに関連するパターンの組み合わせで実現SpringApplicationRunListener外部呼び出しがセットに反復段階のプロセスを実行するプロセスのクラス集合の実装ステージ。実装クラスは、コレクションのあるspring.factoriesクラスを定義したファイル。後で詳細に説明すると、拡張ポイントをここ。

  • EventPublishingRunListener:このクラスは、されてSpring Boot構築されたSpringApplicationRunListener唯一の実装クラスを、そのときの外部呼び出し方法の段階、このクラスのメソッドの実際の実装。

  • SimpleApplicationEventMulticasterは:プロセス段階で、通過するイベント放送を、各段階に対応する放送イベントなどのブロードキャストイベントの方法SpringSimpleApplicationEventMulticasterstartingApplicationStartingEvent

  • ApplicationListener:最後のApplicationListener実装クラスであるSpring Bootイベント、適切なアクションに応じて、イベントの放送にリスナーを聴取。ここではSpring Bootリスナーがでもあるspring.factories良いの定義を、ここでは拡大して自由です。

ここではSpring Bootイベントリスナーメカニズムはほとんど終了し、それがいることは注目に値するSpring Bootリスナーの実装がされて、最後のイベント・クラスは、クラスを継承するクラスを、そのメカニズムはイベントとリスナーに基づいています実現します。SpringApplicationListenerSpringApplicationEventSpring BootSpring

2.2 ApplicationArguments負荷の起動パラメータ

        実行するときに終了listeners.startingする方法を、その後に構成されたApplicationArgumentsステージ。

public class SpringApplication {

    ...
    
    public ConfigurableApplicationContext run(String... args) {
        
        ...
        
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            
            ...
        }
    }
    
    ...
}

このクラスは、単純化するために使用されSpring Boot、我々はプロジェクトがクラスにカプセル化され始めたときにアプリケーションの起動パラメータパッケージ・インタフェース、コマンドパラメータ入力。次のように一つは、IDEAの入力パラメータであります:
画像

他は、springbootcmdを実行します。伝送パラメータのjarパッケージランタイムjava -jar xxx.jar name=张三 pwa=123

その後、によって@Autowired注射ApplicationArgumentsで使用するために:

public class Test {

    @Autowired
    private ApplicationArguments applicationArguments;

    public void getArgs() {
        // 获取 args 中的所有 non option 参数
        applicationArguments.getNonOptionArgs();

        // 获取 args 中所有的 option 参数的 name
        applicationArguments.getOptionNames();

        // 获取传递给应用程序的原始未处理参数
        applicationArguments.getSourceArgs();

        // 获取 args 中指定 name 的 option 参数的值
        applicationArguments.getOptionValues("nmae");

        // 判断从参数中解析的 option 参数是否包含指定名称的选项
        applicationArguments.containsOption("name");
    }
}

外部荷重の2.3 ConfigurableEnvironment構成

        その後、建設入るConfigurableEnvironment相を、クラスは私たちの外部化の設定を処理するために使用され、人気話すには対処することでproperties、文書の構成ファイルを操作するための基礎を提供します。また、Spring Bootあるデフォルトの設定ファイルは、そこにありますapplication.propertiesここでは、一般的に理解することができ、内容を議論するために、この記事の背後に特別ながあるでしょう。私たちは、クラスを作成するために入力prepareEnvironmentする方法を:

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments) {
    // Create and configure the environment
    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;
}

这里通过 getOrCreateEnvironment 方法返回具体的 Environment

private ConfigurableEnvironment getOrCreateEnvironment() {
        if (this.environment != null) {
            return this.environment;
        }
        switch (this.webApplicationType) {
        case SERVLET:
            return new StandardServletEnvironment();
        case REACTIVE:
            return new StandardReactiveWebEnvironment();
        default:
            return new StandardEnvironment();
        }
    }

可以看到,这里通过 webApplicationType 属性来判断当前应用的类型,有 ServletReactive 、 非Web 3种类型,该属性也是在上篇文章中 SpringApplication 准备阶段确定的,这里我们通常都是 Servlet 类型,返回的是 StandardServletEnvironment 实例。

之后,还调用了 SpringApplicationRunListenersenvironmentPrepared 阶段方法,表示 ConfigurableEnvironment 构建完成,同时向 Spring Boot 监听器发布 ApplicationEnvironmentPreparedEvent 事件。监听该事件的监听器有:
画像

2.4 ConfigurableApplicationContext 创建 Spring 应用上下文

        这里通过 createApplicationContext 方法创建 Spring 应用上下文,实际上 Spring 的应用上下文才是驱动 Spring Boot 的核心引擎:

public class SpringApplication {

    ...

    public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
            + "annotation.AnnotationConfigApplicationContext";

    public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
            + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";

    public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework."
            + "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";

    ...

    protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch (this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                    break;
                case REACTIVE:
                    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                    break;
                default:
                    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
                }
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
                        ex);
            }
        }
        return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
    }
    
    ...
}

这里也是通过 webApplicationType 属性来确定应用类型从而创建 String 上下文,上篇文章说到该属性值是在 Spring Boot 准备阶段推导出来的。这里我们的应用类型是 Servlet ,所以创建的是 AnnotationConfigServletWebServerApplicationContext 对象。创建完 Spring 应用上下文之后,执行 prepareContext 方法进入准备上下文阶段:

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
            SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    context.setEnvironment(environment);
    postProcessApplicationContext(context);
    applyInitializers(context);
    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory) beanFactory)
                .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    // Load the sources
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));
    listeners.contextLoaded(context);
}

我们来看看主要做了哪些操作:

  1. 设置了 Spring 应用上下文的 ApplicationArguments,上面说过是处理外部化配置的,具体类型为 StandardServletEnvironment

  2. Spring 应用上下文后置处理,主要是覆盖当前 Spring 应用上下文默认所关联的 ResourceLoaderClassLoader

  3. 执行 Spring 的初始化器,上篇文章说过在 Spring Boot 准备阶段初始化了一批在 spring.factories 文件中定义好的 ApplicationContextInitializer ,这里就是执行它们的 initialize 方法,同时这里也是一个扩展点,后面详细讨论。

  4. 执行 SpringApplicationRunListenerscontextPrepared 阶段方法,表示 ApplicationContext 准备完成,同时向 Spring Boot 监听器发布 ApplicationContextInitializedEvent 事件 。

  5. springApplicationArgumentsspringBootBanner 注册为 Bean

  6. 加载 Spring 应用上下文的配置源,也是在上篇文章 Spring Boot 准备阶段获取的 primarySourcessourcesprimarySources 来源于 SpringApplication 构造器参数,sources 则来源于自定义配置的 setSources 方法。

  7. 最后执行 SpringApplicationRunListenerscontextLoaded 阶段方法,表示 ApplicationContext 完成加载但还未启动,同时向 Spring Boot 监听器发布 ApplicationPreparedEvent 事件 。

接下来就是真正启动阶段,执行的是 refreshContext 方法:

private void refreshContext(ConfigurableApplicationContext context) {
    refresh(context);
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
    }
}
protected void refresh(ApplicationContext applicationContext) {
        Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    ((AbstractApplicationContext) applicationContext).refresh();
}

可以看到,底层调用的是 AbstractApplicationContextrefresh 方法,到这里 Spring 应用正式启动,Spring Boot 核心特性也随之启动,如自动装配。随后执行 SpringApplicationRunListenersstarted 阶段方法,表示 ApplicationContext 已启动,同时向 Spring Boot 监听器发布 ApplicationStartedEvent 事件 。但还未启动完成,后面还有一个 callRunners 方法,一般来讲,里面执行一些我们自定义的操作。之后 Spring 应用才算启动完成,随后调用 running 方法,发布 ApplicationReadyEvent 事件。至此,SpringApplication 运行阶段结束。

3、总结

        最后来对 SpringApplication 运行阶段做一个总结。这个阶段核心还是以启动 Spring 应用上下文为主,同时根据应用类型来初始化不同的上下文对象,但这些对象的基类都是 SpringConfigurableApplicationContext 类。且在启动的各个阶段中,使用 SpringApplicationRunListeners 进行事件广播,回调 Spring Boot 的监听器。同时还初始化了 ApplicationArgumentsConfigurableEnvironment 等几个组件。下篇文章我们就来讨论 Spring Boot 的外部化配置部分,来看看为什么外部的各个组件,如 RedisDubbo 等在 properties 文件中进行相应配置后,就可以正常使用。

以上就是本章的内容,如过文章中有错误或者需要补充的请及时提出,本人感激不尽。



参考:

「春ブーツがアイデアをプログラミング」
https://www.cnblogs.com/youzhibing/p/9603119.html
https://www.jianshu.com/p/b86a7c8b3442
https://www.cnblogs.com/duanxz/p/ 11243271.html
https://www.jianshu.com/p/7a674c59d76e

おすすめ

転載: www.cnblogs.com/loongk/p/12006840.html