中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

免費創(chuàng)辦網(wǎng)站印度疫情最新消息

免費創(chuàng)辦網(wǎng)站,印度疫情最新消息,東莞平面設計公司有哪些,四川南充房產(chǎn)網(wǎng)文章目錄 run方法核心流程SpringApplicationRunListener監(jiān)聽器監(jiān)聽器的配置與加載SpringApplicationRunListener源碼解析實現(xiàn)類EventPublishingRunListener 初始化ApplicationArguments初始化ConfigurableEnvironment獲取或創(chuàng)建環(huán)境配置環(huán)境 打印BannerSpring應用上下文的創(chuàng)建S…

文章目錄

  • run方法核心流程
  • SpringApplicationRunListener監(jiān)聽器
    • 監(jiān)聽器的配置與加載
    • SpringApplicationRunListener源碼解析
    • 實現(xiàn)類EventPublishingRunListener
  • 初始化ApplicationArguments
  • 初始化ConfigurableEnvironment
      • 獲取或創(chuàng)建環(huán)境
      • 配置環(huán)境
  • 打印Banner
  • Spring應用上下文的創(chuàng)建
  • Spring應用上下文的準備
  • Spring應用上下文的刷新
  • 調(diào)用ApplicationRunner和CommandLineRunner

run方法核心流程

在分析和學習整個run方法的源代碼及操作之前,我們先通過下圖所示的流程圖來看一下SpringApplication調(diào)用的run方法處理的核心操作都包含哪些。

在這里插入圖片描述

上面的流程圖可以看出,SpringApplication在run方法中重點做了以下操作。

  • 獲取監(jiān)聽器和參數(shù)配置。
  • 打印Banner信息。
  • 創(chuàng)建并初始化容器。
  • 監(jiān)聽器發(fā)送通知。

當然,除了核心操作,run方法運行過程中還涉及啟動時長統(tǒng)計、異常報告、啟動日志、異常處理等輔助操作。

public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();this.configureHeadlessProperty();SpringApplicationRunListeners listeners = this.getRunListeners(args);listeners.starting();Collection exceptionReporters;try {// 創(chuàng)建 ApplicationArguments 對象ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//  加載屬性配置ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);this.configureIgnoreBeanInfo(environment);//  打印bannerBanner printedBanner = this.printBanner(environment);// 創(chuàng)建容器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);// 停止時長統(tǒng)計stopWatch.stop();//  打印日志if (this.logStartupInfo) {(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);}//  通知監(jiān)聽器容器啟動完成listeners.started(context);this.callRunners(context, applicationArguments);} catch (Throwable var10) {//  異常處理this.handleRunFailure(context, var10, exceptionReporters, listeners);throw new IllegalStateException(var10);}try {//  通知監(jiān)聽器:容器正在運行listeners.running(context);return context;} catch (Throwable var9) {// 異常處理this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);throw new IllegalStateException(var9);}
}

SpringApplicationRunListener監(jiān)聽器

監(jiān)聽器的配置與加載

SpringApplicationRunListeners 可以理解為一個SpringApplicationRunListener的容器,它將SpringApplicationRunListener的集合以構造方法傳入,并賦值給其listeners成員變量,然后提供了針對listeners 成員變量的各種遍歷操作方法,比如,遍歷集合并調(diào)用對應的starting、started、running等方法。

SpringApplicationRunListeners 的構建很簡單,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));
}

SpringApplicationRunListeners構造方法的第二個參數(shù)便是SpringApplicationRunListener的集合,SpringApplication中調(diào)用構造方法時該參數(shù)是通過getSpringFactoriesInstances方法獲取(都是一樣的套路)的,代碼如下:


private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {// 獲取類加載器ClassLoader classLoader = this.getClassLoader();//  加載監(jiān)聽器,并放入set中Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 實例化監(jiān)聽器List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);//  排序AnnotationAwareOrderComparator.sort(instances);return instances;
}

通過方法名便可得知,getSpringFactoriesInstances是用來獲取factories配置文件中的注冊類,并進行實例化操作。

關于通過SpringFactoriesLoader獲取META-INF/spring.factories中對應的配置,構造方法章節(jié)已經(jīng)多次提到,這里不再贊述。SpringApplicationRunListener的注冊配置位于spring-boot項目中的spring.factories文件內(nèi),SpringBoot默認僅有一個監(jiān)聽器進行了注冊,關于其功能后面會專門講到。


private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {List<T> instances = new ArrayList(names.size());Iterator var7 = names.iterator();while(var7.hasNext()) {String name = (String)var7.next();try {Class<?> instanceClass = ClassUtils.forName(name, classLoader);Assert.isAssignable(type, instanceClass);Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);T instance = BeanUtils.instantiateClass(constructor, args);instances.add(instance);} catch (Throwable var12) {throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);}}return instances;
}

在上面的代碼中,實例化監(jiān)聽器時需要有一個默認的構造方法,且構造方法的參數(shù)為Class<?>[]parameterTypes。我們向上追蹤該參數(shù)的來源,會發(fā)現(xiàn)該參數(shù)的值為Class數(shù)組,數(shù)組的內(nèi)容依次為SpringApplication.class和String[].class。也就是說,SpringApplicationRunListener的實現(xiàn)類必須有默認的構造方法,且構造方法的參數(shù)必須依次為SpringApplication和String[]類型。

SpringApplicationRunListener源碼解析

接口SpringApplicationRunListener是SpringApplication的run方法監(jiān)聽器。上節(jié)提到了 SpringApplicationRunListener通過SpringFactoriesLoader加載,并且必須聲明一個公共構造函數(shù),該函數(shù)接收SpringApplication實例和String[]的參數(shù),而且每次運行都會創(chuàng)建一個新的實例。

SpringApplicationRunListener提供了一系列的方法,用戶可以通過回調(diào)這些方法,在啟動各個流程時加入指定的邏輯處理。


class SpringApplicationRunListeners {private final Log log;private final List<SpringApplicationRunListener> listeners;SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {this.log = log;this.listeners = new ArrayList(listeners);}public void starting() {Iterator var1 = this.listeners.iterator();while(var1.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();listener.starting();}}public void environmentPrepared(ConfigurableEnvironment environment) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.environmentPrepared(environment);}}public void contextPrepared(ConfigurableApplicationContext context) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.contextPrepared(context);}}public void contextLoaded(ConfigurableApplicationContext context) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.contextLoaded(context);}}public void started(ConfigurableApplicationContext context) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.started(context);}}public void running(ConfigurableApplicationContext context) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.running(context);}}public void failed(ConfigurableApplicationContext context, Throwable exception) {Iterator var3 = this.listeners.iterator();while(var3.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var3.next();this.callFailedListener(listener, context, exception);}}private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context, Throwable exception) {try {listener.failed(context, exception);} catch (Throwable var6) {if (exception == null) {ReflectionUtils.rethrowRuntimeException(var6);}if (this.log.isDebugEnabled()) {this.log.error("Error handling failed", var6);} else {String message = var6.getMessage();message = message != null ? message : "no error message";this.log.warn("Error handling failed (" + message + ")");}}}
}

我們通過源代碼可以看出,SpringApplicationRunListener為run方法提供了各個運行階段的監(jiān)聽事件處理功能。

下圖展示了在整個run方法的生命周期中SpringApplicationRunListener的所有方法所處的位置,該圖可以幫助我們更好地學習run方法的運行流程。在前面run方法的代碼中已經(jīng)看到相關監(jiān)聽方法被調(diào)用,后續(xù)的源代碼中也將涉及對應方法的調(diào)用,我們可參考此圖以便理解和加深記憶。

在這里插入圖片描述

實現(xiàn)類EventPublishingRunListener

EventPublishingRunListener是SpringBoot中針對SpringApplicationRunListener接口的唯一內(nèi)建實現(xiàn)。EventPublishingRunListener使用內(nèi)置的SimpleApplicationEventMulticaster來廣播在上下文刷新之前觸發(fā)的事件。

默認情況下,SpringBoot在初始化過程中觸發(fā)的事件也是交由EventPublishingRunListener來代理實現(xiàn)的。

SpringBoot完成基本的初始化之后,會遍歷SpringApplication的所有ApplicationListener實例,并將它們與SimpleApplicationEventMulticaster進行關聯(lián),方便SimpleApplicationEventMulticaster后續(xù)將事件傳遞給所有的監(jiān)聽器。

EventPublishingRunListener針對不同的事件提供了不同的處理方法,但它們的處理流程基本相同。


public void contextLoaded(ConfigurableApplicationContext context) {ApplicationListener listener;for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {listener = (ApplicationListener)var2.next();if (listener instanceof ApplicationContextAware) {((ApplicationContextAware)listener).setApplicationContext(context);}}this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}

contextLoaded方法在發(fā)布事件之前做了兩件事:第一,遍歷application的所有監(jiān)聽器實現(xiàn)類,如果該實現(xiàn)類還實現(xiàn)了ApplicationContextAware接口,則將上下文信息設置到該監(jiān)聽器內(nèi);第二,將application中的監(jiān)聽器實現(xiàn)類全部添加到上下文中。最后一步才是調(diào)用事件廣播。

也正是這個方法形成了不同事件廣播形式的分水嶺,在此方法之前執(zhí)行的事件廣播都是通過multicastEvent來進行的,而該方法之后的方法則均采用publishEvent來執(zhí)行。這是因為只有到了contextLoaded方法之后,上下文才算初始化完成,才可通過它的publishEvent方法來進行事件的發(fā)布。

初始化ApplicationArguments

監(jiān)聽器啟動之后,緊接著便是執(zhí)行ApplicationArguments對象的初始化,ApplicationArguments是用于提供訪問運行SpringApplication時的參數(shù)。

ApplicationArguments的初始化過程非常簡單,只是調(diào)用了它的實現(xiàn)類DefaultApplicationArguments并傳入main方法中的args參數(shù)。

在DefaultApplicationArguments中將參數(shù)args封裝為Source對象,Source對象是基于Spring框架的SimpleCommandLinePropertySource來實現(xiàn)的。

初始化ConfigurableEnvironment

完成ApplicationArguments參數(shù)的準備之后,便開始通過prepareEnvironment方法對ConfigurableEnvironment對象進行初始化操作。

ConfigurableEnvironment接口繼承自Environment接口和ConfigurablePropertyResolver,最終都繼承自接口PropertyResolverConfigurableEnvironment接口的主要作用是提供當前運行環(huán)境的公開接口,比如配置文件profiles各類系統(tǒng)屬性和變量的設置、添加、讀取、合并等功能。

通過ConfigurableEnvironment接口中方法定義,可以更清楚地了解它的功能,代碼如下:


public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {void setActiveProfiles(String... var1);void addActiveProfile(String var1);void setDefaultProfiles(String... var1);MutablePropertySources getPropertySources();Map<String, Object> getSystemProperties();Map<String, Object> getSystemEnvironment();void merge(ConfigurableEnvironment var1);
}

通過接口提供的方法,我們可以看出ConfigurableEnvironment就是圍繞著這個“環(huán)境”來提供相應的功能,這也是為什么我們也將它稱作“環(huán)境”。

了解了ConfigurableEnvironment的功能及方法,我們回歸到SpringApplication的流程看相關源代碼。run方法中調(diào)用prepareEnvironment方法相關代碼如下:


private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {ConfigurableEnvironment environment = this.getOrCreateEnvironment();this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());listeners.environmentPrepared((ConfigurableEnvironment)environment);this.bindToSpringApplication((ConfigurableEnvironment)environment);if (!this.isCustomEnvironment) {environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());}ConfigurationPropertySources.attach((Environment)environment);return (ConfigurableEnvironment)environment;
}

通過以上代碼可知,prepareEnvironment進行了以下的操作:

  • 獲取或創(chuàng)建環(huán)境。
  • 配置環(huán)境。
  • ConfigurationPropertySources附加到指定環(huán)境:將ConfigurationPropertySources附加到指定環(huán)境中的第一位,并動態(tài)跟蹤環(huán)境的添加或刪除(當前版本新增了該行代碼,與最后一步操作相同)。
  • 設置listener監(jiān)聽事件:前面章節(jié)已經(jīng)講過,此處主要針對準備環(huán)境的監(jiān)聽。
  • 綁定環(huán)境到SpringApplication:將環(huán)境綁定到name為“spring.main”的目標上。
  • 轉換環(huán)境:判斷是否是定制的環(huán)境,如果不是定制的,則將環(huán)境轉換為StandardEnvironment。此時判斷條件isCustomEnvironment默認為false,在后面的操作中會將其設置為true,如果為true則不再會進行此轉換操作。
  • ConfigurationPropertySources附加到指定環(huán)境:將ConfigurationPropertySources附加到指定環(huán)境中的第一位,并動態(tài)跟蹤環(huán)境的添加或刪除操作。

獲取或創(chuàng)建環(huán)境

SpringApplication類中通過getOrCreateEnvironment方法來獲取或創(chuàng)建環(huán)境。在該方法中首先判斷環(huán)境是否為null,如果不為null則直接返回;如果為null,則根據(jù)前面推斷出來的WebApplicationType類型來創(chuàng)建指定的環(huán)境。

配置環(huán)境

在獲得環(huán)境變量對象之后,開始對環(huán)境變量和參數(shù)進行相應的設置,主要包括轉換服務的設置、PropertySources的設置和activeProfiles的設置。

打印Banner

完成環(huán)境的基本處理之后,下面就是控制臺Banner的打印了。SpringBoot的Banner打印是一個比較酷炫的功能,但又顯得有些華而不實,特別是打印圖片時啟動速度會變慢。

private Banner printBanner(ConfigurableEnvironment environment) {if (this.bannerMode == Mode.OFF) {return null;} else {ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader(this.getClassLoader());SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter((ResourceLoader)resourceLoader, this.banner);return this.bannerMode == Mode.LOG ? bannerPrinter.print(environment, this.mainApplicationClass, logger) : bannerPrinter.print(environment, this.mainApplicationClass, System.out);}
}

上面的代碼中展示了Banner的開啟及打印位置的設置。程序通過Banner.Mode枚舉值來判斷是否開啟Banner打印,此項參數(shù)可以在SpringBoot入口nmain方法中通過setBannerMode方法來設置,也可以通過application.properties中的spring.main.banner-mode進行設置。

SpringApplicationBannerPrinter類承載了Banner初始化及打印的核心功能,比如默認如何獲取Banner信息、如何根據(jù)約定優(yōu)于配置來默認獲得Banner的內(nèi)容、Banner支持的文件格式等。

而具體打印的信息是由Banner接口的實現(xiàn)類來完成的,比如默認情況下使用SpringBootBanner來打印SpringBoot的版本信息及簡單的圖形。當然還有通過資源文件打印的ResourceBanner,通過圖片打印的ImageBanner等方法。

Spring應用上下文的創(chuàng)建

SpringBoot創(chuàng)建Spring的應用上下文時,如果未指定要創(chuàng)建的類,則會根據(jù)之前推斷出的類型來進行默認上下文類的創(chuàng)建。

在SpringBoot中通過SpringApplication類中的createApplicationContext來進行應用上下文的創(chuàng)建,代碼如下:


protected ConfigurableApplicationContext createApplicationContext() {//  獲取容器的類變量Class<?> contextClass = this.applicationContextClass;//  如果為null,則根據(jù)Web應用類型按照默認類進行創(chuàng)建if (contextClass == null) {try {switch(this.webApplicationType) {case SERVLET:contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");break;case REACTIVE:contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");break;default:contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");}} catch (ClassNotFoundException var3) {throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);}}return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}

Spring應用上下文的準備

我們在上一節(jié)完成了應用上下文的創(chuàng)建工作,SpringApplication繼續(xù)通過prepareContext方法來進行應用上下文的準備工作。


private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {// 設置應用上下文環(huán)境context.setEnvironment(environment);// 設置應用上下文后置處理this.postProcessApplicationContext(context);// 初始化contextthis.applyInitializers(context);// 通知監(jiān)聽器上下文準備階段listeners.contextPrepared(context);// 打印 profileif (this.logStartupInfo) {this.logStartupInfo(context.getParent() == null);this.logStartupProfileInfo(context);}//  獲取 ConfigurableListableBeanFactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}//  獲取全部配置源Set<Object> sources = this.getAllSources();Assert.notEmpty(sources, "Sources must not be empty");//  將獲取到的配置源加載到context中this.load(context, sources.toArray(new Object[0]));//  通知監(jiān)聽器 context 加載完成listeners.contextLoaded(context);
}

Spring應用上下文的刷新

Spring應用上下文的刷新,是通過調(diào)用SpringApplication中的refreshContext方法來完成的。SpringApplication中refreshContext方法相關代碼如下:


private void refreshContext(ConfigurableApplicationContext context) {this.refresh(context);if (this.registerShutdownHook) {try {context.registerShutdownHook();} catch (AccessControlException var3) {}}}protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);((AbstractApplicationContext)applicationContext).refresh();
}

其中refresh方法調(diào)用的是AbstractApplicationContext中的refresh方法,該類屬于spring-context包。AbstractApplicationContext的refresh方法更多的是Spring相關的內(nèi)容。


public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {this.prepareRefresh();ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();this.prepareBeanFactory(beanFactory);try {this.postProcessBeanFactory(beanFactory);this.invokeBeanFactoryPostProcessors(beanFactory);this.registerBeanPostProcessors(beanFactory);this.initMessageSource();this.initApplicationEventMulticaster();this.onRefresh();this.registerListeners();this.finishBeanFactoryInitialization(beanFactory);this.finishRefresh();} catch (BeansException var9) {if (this.logger.isWarnEnabled()) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);}this.destroyBeans();this.cancelRefresh(var9);throw var9;} finally {this.resetCommonCaches();}}
}

在上面的代碼中,調(diào)用finishRefresh方法初始化容器的生命周期處理器并發(fā)布容器的生命周期事件之后,Spring應用上下文正式開啟,SpringBoot核心特性也隨之啟動。完成refreshContext方法操作之后,調(diào)用afterRefresh方法。

完成以上操作之后,調(diào)用SpringApplicationRunListeners的started方法,通知監(jiān)聽器容器啟動完成,并調(diào)用ApplicationRunner和CommandLineRunner的運行方法。

調(diào)用ApplicationRunner和CommandLineRunner

ApplicationRunner和CommandLineRunner是通過 SpringApplication類的callRunners方法來完成的,具體代碼如下:


private void callRunners(ApplicationContext context, ApplicationArguments args) {List<Object> runners = new ArrayList();runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());AnnotationAwareOrderComparator.sort(runners);Iterator var4 = (new LinkedHashSet(runners)).iterator();while(var4.hasNext()) {Object runner = var4.next();if (runner instanceof ApplicationRunner) {this.callRunner((ApplicationRunner)runner, args);}if (runner instanceof CommandLineRunner) {this.callRunner((CommandLineRunner)runner, args);}}}

以上代碼,首先從context中獲得類型為ApplicationRunner和CommandLineRunner的Bean,將它們放入List列表中并進行排序。然后再遍歷調(diào)用其run方法,并將ApplicationArguments參數(shù)傳入。

SpringBoot提供這兩個接口的目的,是為了我們在開發(fā)的過程中,通過它們來實現(xiàn)在容器啟動時執(zhí)行一些操作,如果有多個實現(xiàn)類,可通過@Order注解或實現(xiàn)Ordered接口來控制執(zhí)行順序。

這兩個接口都提供了一個run方法,但不同之處在于:ApplicationRunner中run方法的參數(shù)為ApplicationArguments,而CommandLineRunner接口中run方法的參數(shù)為String數(shù)組。

以上方法執(zhí)行完成后,會通過SpringApplicationRunListeners的running方法通知監(jiān)聽器:容器此刻已處于運行狀態(tài)。至此,SpringApplication的run方法執(zhí)行完畢。

http://www.risenshineclean.com/news/43728.html

相關文章:

  • 99到家網(wǎng)站怎么做客戶關系管理
  • 娛樂網(wǎng)站建設公司營銷軟件有哪些
  • 怎么搭建自己的博客網(wǎng)站百度網(wǎng)頁版入口鏈接
  • 有名網(wǎng)站建設公司百度網(wǎng)盤pc端網(wǎng)頁版
  • 網(wǎng)站建設測試流程圖友情鏈接如何添加
  • 怎么增加網(wǎng)站的外鏈學校網(wǎng)站建設
  • 網(wǎng)站設計任務書范文站長工具seo綜合查詢訪問
  • 精通網(wǎng)站建設 全能建站密碼pdf理發(fā)美發(fā)培訓學校
  • 公司網(wǎng)站制作推廣公司
  • 電子商務網(wǎng)站有哪幾種搜索引擎營銷的常見方式
  • 網(wǎng)站代理游戲合川網(wǎng)站建設
  • 蘇州專業(yè)高端網(wǎng)站建設公司專業(yè)制作網(wǎng)站的公司哪家好
  • 泰州網(wǎng)站建設服務熱線全網(wǎng)推廣軟件
  • 免費推廣網(wǎng)站2023mmm網(wǎng)絡營銷項目
  • 桐鄉(xiāng)住房和城鄉(xiāng)規(guī)劃建設局網(wǎng)站如何做網(wǎng)絡銷售產(chǎn)品
  • 上海網(wǎng)站設計工具網(wǎng)絡推廣運營團隊
  • 建設廳特種作業(yè)證件查詢官網(wǎng)網(wǎng)站優(yōu)化推廣公司
  • 重慶品牌網(wǎng)站建設優(yōu)化網(wǎng)站排名方法
  • 網(wǎng)站設計導航欄高度佛山市人民政府門戶網(wǎng)站
  • 網(wǎng)站建設詢價文件無錫營銷型網(wǎng)站制作
  • 海爾集團電商網(wǎng)站建設百度網(wǎng)頁版進入
  • 怎樣在國外網(wǎng)站做推廣搜索關鍵詞排名一般按照什么收費
  • 做網(wǎng)站做軟件怎么賺錢嗎搜索量最大的關鍵詞
  • 咸秧草做哪些網(wǎng)站優(yōu)化大師免安裝版
  • 鄭州做網(wǎng)站推廣外包產(chǎn)品推廣方式
  • 鞍山網(wǎng)站制作公司優(yōu)化綠松石什么意思
  • 泉州建設網(wǎng)站開發(fā)快速排名優(yōu)化
  • 湖南做網(wǎng)站磐石網(wǎng)絡案例cba最新排名
  • 淘寶的網(wǎng)站建設seo分析報告怎么寫
  • 網(wǎng)站如何提高權重做百度推廣怎么做才能有電話