首頁>Club>
5
回覆列表
  • 1 # 樂創業

    程式入口

    SpringApplication.run(BeautyApplication.class, args);

    執行此方法來載入整個SpringBoot的環境。

    1. 從哪兒開始?

    SpringApplication.java

    /**

    * Run the Spring application, creating and refreshing a new

    * {@link ApplicationContext}.

    * @param args the application arguments (usually passed from a Java main method)

    * @return a running {@link ApplicationContext}

    */

    public ConfigurableApplicationContext run(String... args) {

    //...

    }

    呼叫SpringApplication.java 中的 run 方法,目的是載入Spring Application,同時返回 ApplicationContext。

    2. 執行了什麼?

    2.1 計時

    記錄整個Spring Application的載入時間!

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    // ...

    stopWatch.stop();

    if (this.logStartupInfo) {

    new StartupInfoLogger(this.mainApplicationClass)

    .logStarted(getApplicationLog(), stopWatch);

    }

    2.2 宣告

    指定 java.awt.headless,預設是true 一般是在程式開始啟用headless模式,告訴程式,現在你要工作在Headless mode下,就不要指望硬體幫忙了,你得自力更生,依靠系統的計算能力模擬出這些特性來。

    private void configureHeadlessProperty() {

    System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(

    SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));

    }

    2.4 配置監聽併發布應用啟動事件

    SpringApplicationRunListener 負責載入 ApplicationListener事件。

    SpringApplicationRunListeners listeners = getRunListeners(args);

    // 開始

    listeners.starting();

    // 處理所有 property sources 配置和 profiles 配置,準備環境,分為標準 Servlet 環境和標準環境

    ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);

    // 準備應用上下文

    prepareContext(context, environment, listeners, applicationArguments,printedBanner);

    // 完成

    listeners.started(context);

    // 異常

    handleRunFailure(context, ex, exceptionReporters, listeners);

    // 執行

    listeners.running(context);

    getRunListeners 中根據 type = SpringApplicationRunListener.class 去拿到了所有的 Listener 並根據優先順序排序。

    對應的就是 META-INF/spring.factories 檔案中的 org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener

    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,

    Class<?>[] parameterTypes, Object... args) {

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

    // 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;

    }

    複製程式碼

    在 ApplicationListener 中 , 可以針對任何一個階段插入處理程式碼。

    public interface SpringApplicationRunListener {

    /**

    * Called immediately when the run method has first started. Can be used for very

    * early initialization.

    */

    void starting();

    /**

    * Called once the environment has been prepared, but before the

    * {@link ApplicationContext} has been created.

    * @param environment the environment

    */

    void environmentPrepared(ConfigurableEnvironment environment);

    /**

    * Called once the {@link ApplicationContext} has been created and prepared, but

    * before sources have been loaded.

    * @param context the application context

    */

    void contextPrepared(ConfigurableApplicationContext context);

    /**

    * Called once the application context has been loaded but before it has been

    * refreshed.

    * @param context the application context

    */

    void contextLoaded(ConfigurableApplicationContext context);

    /**

    * The context has been refreshed and the application has started but

    * {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner

    * ApplicationRunners} have not been called.

    * @param context the application context.

    * @since 2.0.0

    */

    void started(ConfigurableApplicationContext context);

    /**

    * Called immediately before the run method finishes, when the application context has

    * been refreshed and all {@link CommandLineRunner CommandLineRunners} and

    * {@link ApplicationRunner ApplicationRunners} have been called.

    * @param context the application context.

    * @since 2.0.0

    */

    void running(ConfigurableApplicationContext context);

    /**

    * Called when a failure occurs when running the application.

    * @param context the application context or {@code null} if a failure occurred before

    * the context was created

    * @param exception the failure

    * @since 2.0.0

    */

    void failed(ConfigurableApplicationContext context, Throwable exception);

    }

    3. 每個階段執行的內容

    3.1 listeners.starting();

    在載入Spring Application之前執行,所有資源和環境未被載入。

    3.2 prepareEnvironment(listeners, applicationArguments);

    建立 ConfigurableEnvironment; 將配置的環境繫結到Spring Application中;

    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.webApplicationType == WebApplicationType.NONE) {

    environment = new EnvironmentConverter(getClassLoader())

    .convertToStandardEnvironmentIfNecessary(environment);

    }

    ConfigurationPropertySources.attach(environment);

    return environment;

    }

    3.3 prepareContext

    配置忽略的Bean;

    private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {

    if (System.getProperty(

    CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {

    Boolean ignore = environment.getProperty("spring.beaninfo.ignore",

    Boolean.class, Boolean.TRUE);

    System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,

    ignore.toString());

    }

    }

    列印日誌-載入的資源

    Banner printedBanner = printBanner(environment);

    根據不同的WebApplicationType建立Context

    context = createApplicationContext();

    3.4 refreshContext

    支援定製重新整理

    /**

    * Register a shutdown hook with the JVM runtime, closing this context

    * on JVM shutdown unless it has already been closed at that time.

    * <p>This method can be called multiple times. Only one shutdown hook

    * (at max) will be registered for each context instance.

    * @see java.lang.Runtime#addShutdownHook

    * @see #close()

    */

    void registerShutdownHook();

    3.5 afterRefresh

    重新整理後的實現方法暫未實現

    /**

    * Called after the context has been refreshed.

    * @param context the application context

    * @param args the application arguments

    */

    protected void afterRefresh(ConfigurableApplicationContext context,

    ApplicationArguments args) {

    }

    3.6 listeners.started(context);

    到此為止, Spring Application的環境和資源都載入完畢了; 釋出應用上下文啟動完成事件; 執行所有 Runner 執行器 - 執行所有 ApplicationRunner 和 CommandLineRunner 這兩種執行器

    // 啟動

    callRunners(context, applicationArguments);

    3.7 listeners.running(context);

    觸發所有 SpringApplicationRunListener 監聽器的 running 事件方法

  • 中秋節和大豐收的關聯?
  • linux怎麼編譯c的源程式的?gcc,編譯命令是什麼?