1.Spring Boot 簡介
簡化Spring應用開發的一個框架;
內嵌Servler容器
減少了配置文件
2.微服務
每一個功能元素最終都是一個可獨立替換和獨立升級的軟件單元;
3.打包插件
<!-- 這個插件,可以將應用打包成一個可執行的jar包;-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
將這個應用打成jar包,直接使用java -jar的命令進行執行;
4.Spring boot父POM文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
他的父項目是
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
他來真正管理Spring Boot應用裏面的所有依賴版本;
Spring Boot的版本仲裁中心;
以後我們導入依賴默認是不需要寫版本;(沒有在dependencies裏面管理的依賴自然需要聲明版本號)
5.激活指定profile
1、在配置文件中指定 spring.profiles.active=dev
2、命令行:
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
可以直接在測試的時候,配置傳入命令行參數
3、虛擬機參數;
-Dspring.profiles.active=dev
6.配置文件加載位置
springboot 啓動會掃描以下位置的application.properties或者application.yml文件作爲Spring boot的默認配置文件
–file:./config/
–file:./
–classpath:/config/
–classpath:/
優先級由高到底,高優先級的配置會覆蓋低優先級的配置;
SpringBoot會從這四個位置全部加載主配置文件;互補配置;
7.spring boot啓動器
導入web容器正常運行所依賴組件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Spring Boot將所有的功能場景都抽取出來,做成一個個的starters(啓動器),只需要在項目裏面引入這些starter相關場景的所有依賴都會導入進來。要用什麼功能就導入什麼場景的啓動器
8.spring啓動原理
/**
* @SpringBootApplication 來標註一個主程序類,說明這是一個Spring Boot應用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// Spring應用啓動起來
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
@SpringBootApplication: Spring Boot應用標註在某個類上說明這個類是SpringBoot的主配置類,SpringBoot運行這個類的main方法來啓動SpringBoot應用;
6.1 springBootApplication註解信息
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//是個配置類
@Configuration(proxyBeanMethods = false)
public @interface SpringBootConfiguration {}
6.2 @SpringBootConfiguration
- @SpringBootConfiguration:Spring Boot的配置類,標註在某個類上,表示這是一個Spring Boot的配置類;
- @Configuration:配置類上來標註這個註解;是個配置類,代替以前的配置文件,配置類也是容器中的一個組件;@Component
6.3@EnableAutoConfiguration
@EnableAutoConfiguration:開啓自動配置功能,以前我們需要配置的東西,Spring Boot幫我們自動配置;告訴SpringBoot開啓自動配置功能;這樣自動配置才能生效;
@AutoConfigurationPackage//自動配置包
@Import(EnableAutoConfigurationImportSelector.class)//給容器中導入一個組件,導入的組件由AutoConfigurationPackages.Registrar.class;
public @interface EnableAutoConfiguration {}
- @AutoConfigurationPackage:自動配置包
@Import(AutoConfigurationPackages.Registrar.class):給容器中導入一個組件,主配置類(@SpringBootApplication標註的類)的所在包及下面所有子包裏面的所有組件掃描到Spring容器
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)//給容器中導入一個組件,導入的組件由AutoConfigurationPackages.Registrar.class;
public @interface AutoConfigurationPackage {}
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//主配置類的所在包及下面所有子包裏面的所有組件掃描到Spring容器
register(registry, new PackageImport(metadata).getPackageName());
}
}
-
@Import(EnableAutoConfigurationImportSelector.class)
給容器導入EnableAutoConfigurationImportSelector組件,將所有需要導入的組件以全類名的方式返回,這些組件將被添加都容器中 ,**會給容器中導入非常多的自動配置類(xxxAutoConfiguration);就是給容器中導入這個場景需要的所有組件,並配置好這些組件;**有了自動配置類,免去了我們手動編寫配置注入功能組件等的工作;@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } //核心在getAutoConfigurationEntry裏面的 List<String> configurations =SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); //掃描所有jar包從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration**指定的值(上面截圖),將這些值作爲自動配置類導入到容器中
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UYCPJtHY-1576169155091)(/Users/laiyanxin/Library/Application Support/typora-user-images/image-20191209230257265.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-p3ncr8O5-1576169155093)(/Users/laiyanxin/Library/Application Support/typora-user-images/image-20191209230646961.png)]
裏面SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);主要是Spring Boot在啓動的時候掃描所有jar包從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration指定的值(上面截圖),將這些值作爲自動配置類導入到容器中,自動配置類就生效,幫我們進行自動配置工作;以前我們需要自己配置的東西,自動配置類都幫我們
- 以**HttpEncodingAutoConfiguration(Http編碼自動配置)**爲例解釋自動配置原理;
@Configuration(proxyBeanMethods = false)//表示這個一個配置類,以前編寫的配置文件一樣,也可以給容器添加組件
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {}
9.SpringMVC自動配置原理
9.1Spring MVC auto-configuration
官方文檔解釋
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
The auto-configuration adds the following features on top of Spring’s defaults:
- Inclusion of
ContentNegotiatingViewResolver
andBeanNameViewResolver
beans.- 自動配置了ViewResolver(視圖解析器:根據方法的返回值得到視圖對象(View),視圖對象決定如何渲染(是轉發還是重定向)
- ContentNegotiatingViewResolver組合了所有視圖解析器
- 我們可以自己給容器中添加一個視圖解析器;自動的將其組合進來.會加入ContentNegotiatingViewResolver
- Support for serving static resources, including support for WebJars (see below).
支持靜態資源文件webjar - Automatic registration of
Converter
,GenericConverter
,Formatter
beans.- 自動註冊了
Converter
,GenericConverter
,Formatter
beans Converter
:轉換器,例子:我們接受對象Person,類型轉換用ConverterFormatter
:格式化器;例子:前端傳2019.12.12通過格式化器轉成Date- 自己添加的格式化器轉換器,我們只需要放在容器中即可=
- 自動註冊了
- Support for
HttpMessageConverters
(see below).- HttpMessageConverter:SpringMVC用來轉換Http請求和響應的;User—Json;
HttpMessageConverters
是從容器中確定;獲取所有的HttpMessageConverter;- 自己給容器中添加HttpMessageConverter,只需要將自己的組件註冊容器中@Bean,@Component
- Automatic registration of
MessageCodesResolver
(see below).
定義錯誤代碼生成規則 - Static
index.html
support. 靜態首頁訪問 - Custom
Favicon
support (see below). - Automatic use of a
ConfigurableWebBindingInitializer
bean (see below).- 我們可以配置一個ConfigurableWebBindingInitializer來替換默認的
- 初始化WebDataBinder;請求數據=====JavaBean;
If you want to keep Spring Boot MVC features, and you just want to add additional MVC configuration (interceptors, formatters, view controllers etc.) you can add your own @Configuration
class of type WebMvcConfigurerAdapter
, but without @EnableWebMvc
. If you wish to provide custom instances of RequestMappingHandlerMapping
, RequestMappingHandlerAdapter
or ExceptionHandlerExceptionResolver
you can declare a WebMvcRegistrationsAdapter
instance providing such components.
If you want to take complete control of Spring MVC, you can add your own @Configuration
annotated with @EnableWebMvc
.
9.2、擴展SpringMVC
編寫一個配置類(@Configuration),是WebMvcConfigurerAdapter類型;不能標註@EnableWebMvc
既保留了所有的自動配置,也能用我們擴展的配置;
使用WebMvcConfigurerAdapter可以來擴展SpringMVC的功能
//使用WebMvcConfigurerAdapter可以來擴展SpringMVC的功能
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//瀏覽器發送 /xx 請求來到 success
registry.addViewController("/xx").setViewName("success");
}
}
原理:
-
WebMvcAutoConfiguration是SpringMVC的自動配置類
-
在做其他自動配置時會導入;@Import(EnableWebMvcConfiguration.class)
@Configuration public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); //從容器中獲取所有的WebMvcConfigurer List<WebMvcConfigurer> configurers @Autowired(required = false) public void setConfigurers(List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { this.configurers.addWebMvcConfigurers(configurers); //一個參考實現;將所有的WebMvcConfigurer相關配置都來一起調用; @Override // public void addViewControllers(ViewControllerRegistry registry) { // for (WebMvcConfigurer delegate : this.delegates) { // delegate.addViewControllers(registry); // } } } }
-
容器中所有的WebMvcConfigurer都會一起起作用;
-
我們的配置類也會被調用;
效果:SpringMVC的自動配置和我們的擴展配置都會起作用;
9.3全面接管SpringMVC
SpringBoot對SpringMVC的自動配置不需要了,所有都是我們自己配置;所有的SpringMVC的自動配置都失效了我們需要在配置類中添加@EnableWebMvc即可
//使用WebMvcConfigurerAdapter可以來擴展SpringMVC的功能
@EnableWebMvc
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// super.addViewControllers(registry);
//瀏覽器發送 /atguigu 請求來到 success
registry.addViewController("/atguigu").setViewName("success");
}
}
原理:爲什麼@EnableWebMvc自動配置就失效了;
-
@EnableWebMvc的核心
@Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc {
-
@Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {}
-
容器中沒有WebMvcConfigurationSupport這個組件的時候,這個自動配置類才生效
@Configuration @ConditionalOnWebApplication @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class }) //容器中沒有這個組件的時候,這個自動配置類才生效 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration {
-
@EnableWebMvc將WebMvcConfigurationSupport組件導入進來;
-
導入的WebMvcConfigurationSupport只是SpringMVC最基本的功能;
10.如何修改SpringBoot的默認配置
- SpringBoot在自動配置很多組件的時候,先看容器中有沒有用戶自己配置的(@Bean、@Component)如果有就用用戶配置的,如果沒有,才自動配置;如果有些組件可以有多個(ViewResolver)將用戶配置的和自己默認的組合起來;
- 在SpringBoot中會有非常多的xxxConfigurer幫助我們進行擴展配置
- 在SpringBoot中會有很多的xxxCustomizer幫助我們進行定製配置
11.嵌入式Servlet容器自動配置原理
EmbeddedServletContainerAutoConfiguration:嵌入式的Servlet容器自動配置
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@Import(BeanPostProcessorsRegistrar.class)
//導入BeanPostProcessorsRegistrar:給容器中導入一些組件
//導入了EmbeddedServletContainerCustomizerBeanPostProcessor:
public class EmbeddedServletContainerAutoConfiguration {
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })//判斷當前是否引入了Tomcat依賴;
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)//判斷當前容器沒有用戶自己定義EmbeddedServletContainerFactory:嵌入式的Servlet容器工廠;作用:創建嵌入式的Servlet容器
public static class EmbeddedTomcat {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}
}
/**
*判斷當前是否引入了Jetty依賴;
**/
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
WebAppContext.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedJetty {
@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
return new JettyEmbeddedServletContainerFactory();
}
}
/**
* 判斷當前是否引入了Undertow依賴
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedUndertow {
@Bean
public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
return new UndertowEmbeddedServletContainerFactory();
}
}
springboot會根據你導入的依賴來選擇servlet容器
3)、以TomcatEmbeddedServletContainerFactory爲例
@Override
public EmbeddedServletContainer getEmbeddedServletContainer(
ServletContextInitializer... initializers) {
//創建一個Tomcat
Tomcat tomcat = new Tomcat();
//配置Tomcat的基本環節
File baseDir = (this.baseDirectory != null ? this.baseDirectory
: createTempDir("tomcat"));
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
//將配置好的Tomcat傳入進去,返回一個EmbeddedServletContainer;並且啓動Tomcat服務器
return getTomcatEmbeddedServletContainer(tomcat);
}
4)、我們對嵌入式容器的配置修改是怎麼生效?
可以通過ServerProperties(也是定製器)配置文件、EmbeddedServletContainerCustomizer 定製器幫我們修改
5)、修改的原理
容器中導入了EmbeddedServletContainerCustomizerBeanPostProcessor
//初始化之前
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
//如果當前初始化的是一個ConfigurableEmbeddedServletContainer類型的組件
if (bean instanceof ConfigurableEmbeddedServletContainer) {
//
postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
}
return bean;
}
private void postProcessBeforeInitialization(
ConfigurableEmbeddedServletContainer bean) {
//獲取所有的定製器,調用每一個定製器的customize方法來給Servlet容器進行屬性賦值;
for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
customizer.customize(bean);
}
}
private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
this.beanFactory
//從容器中獲取所有這葛類型的組件:EmbeddedServletContainerCustomizer
//定製Servlet容器,給容器中可以添加一個EmbeddedServletContainerCustomizer類型的組件
.getBeansOfType(EmbeddedServletContainerCustomizer.class,
false, false)
.values());
Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
步驟:
1)、SpringBoot根據導入的依賴情況,給容器中添加相應的EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】
2)、容器中某個組件要創建對象就會通過後置處理器;EmbeddedServletContainerCustomizerBeanPostProcessor;
只要是嵌入式的Servlet容器工廠,後置處理器就工作;
3)、後置處理器,從容器中獲取所有的EmbeddedServletContainerCustomizer,調用定製器的定製方法
12嵌入式的Servlet容器啓動原理
什麼時候創建嵌入式的Servlet容器工廠?什麼時候獲取嵌入式的Servlet容器並啓動Tomcat;
IOC容器啓動創建嵌入式的Servlet容器
源碼:
獲取嵌入式的Servlet容器工廠:
1)、SpringBoot應用啓動運行run方法
2)、refreshContext(context);
SpringBoot刷新IOC容器【創建IOC容器對象,並初始化容器,創建容器中的每一個組件】;如果是web應用創建AnnotationConfigEmbeddedWebApplicationContext,否則:AnnotationConfigApplicationContext
3)、refresh(context);刷新剛纔創建好的ioc容器;
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
4)、 onRefresh(); web的ioc容器重寫了onRefresh方法
5)、webioc容器會創建嵌入式的Servlet容器;createEmbeddedServletContainer();
6)、獲取嵌入式的Servlet容器工廠:
EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
從ioc容器中獲取EmbeddedServletContainerFactory 組件;TomcatEmbeddedServletContainerFactory創建對象,後置處理器一看是這個對象,就獲取所有的定製器來先定製Servlet容器的相關配置;
7)、使用容器工廠獲取嵌入式的Servlet容器:this.embeddedServletContainer = containerFactory .getEmbeddedServletContainer(getSelfInitializer());
8)、嵌入式的Servlet容器創建對象並啓動Servlet容器;
先啓動嵌入式的Servlet容器,再將ioc容器中剩下沒有創建出的對象獲取出來;
13啓動原理
啓動流程
1.創建SpringApplication對象,在該對象初始化時,找到配置的事件監聽器,並保存起來
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
public SpringApplication(Object... sources) {
initialize(sources);
}
private void initialize(Object[] sources) {
//保存主配置類
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//判斷當前環境是不是Web環境
this.webEnvironment = deduceWebEnvironment();
//從類路徑下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然後保存起來
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//從類路徑下找到ETA-INF/spring.factories配置的所有ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//從多個配置類中找到有main方法的主配置類
this.mainApplicationClass = deduceMainApplicationClass();
}
2.運行run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
//1.獲取SpringApplicationRunListeners;從類路徑下META-INF/spring.factories
SpringApplicationRunListeners listeners = getRunListeners(args);
//2/回調所有的SpringApplicationRunListeners的starting
listeners.starting();
try {
//3.封裝命令航參數
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//4.準備環境,回調SpringApplicationRunListeners的environmentPrepared,表示環境準保完成
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//5.打印banner
Banner printedBanner = printBanner(environment);
//6.根據環境來決定是創建Web還是IOC容器
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
//7.準備上下文環境,
//7.1回調上一步保存的所有ApplicationContextInitializer的initialize方法
//7.2回調SpringApplicationRunListeners的contextPrepared
//7.3最後一步回調SpringApplicationRunListeners的contextLoaded
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//8.刷新容器(如果是web應用還會創建嵌入式的Tomca).掃描,創建,加載所有組件的地方;(配置類,組件,自動配置)
refreshContext(context);
//9.從ioc容器中獲取所有的ApplicationRunner和CommandLineRunner進行回調
//ApplicationRunner先回調,CommandLineRunner再回調
afterRefresh(context, applicationArguments);
//10回調SpringApplicationRunListeners的finished
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
//整個SpringBoot應用啓動完成以後返回啓動的ioc容器;
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
- 獲取SpringApplicationRunListeners;從類路徑下META-INF/spring.factories
- 回調所有的SpringApplicationRunListeners的starting
- 封裝命令行參數
- 準備環境,回調SpringApplicationRunListeners的environmentPrepared,表示環境準保完成
- 打印banner
- 根據環境來決定是創建Web還是IOC容器
- 準備上下文環境,
- 7.1回調上一步保存的所有ApplicationContextInitializer的initialize方法
- 7.2回調SpringApplicationRunListeners的contextPrepared
- 7.3最後一步回調SpringApplicationRunListeners的contextLoaded
- 刷新容器(如果是web應用還會創建嵌入式的Tomca).掃描,創建,加載所有組件的地方;(配置類,組件,自動配置)
- 從ioc容器中獲取所有的ApplicationRunner和CommandLineRunner進行回調,ApplicationRunner先回調,CommandLineRunner再回調
- 回調SpringApplicationRunListeners的finished
- 整個SpringBoot應用啓動完成以後返回啓動的ioc容器;