springboot核心原理:
1.基于springmvc无配置文件完全注解化 + 内置web容器实现springboot框架。main函数方式的启动
2.通过maven快速整合第三方框架
springboot两个核心
内置的Tomcat(ServletWebServerFactoryAutoConfiguration)
dispatcherServlet(DispathcerServletAutoConfiguration)
springboot启动流程
1.创建SpringApplication对象
2.调用SpringApplication.run()方法启动项目,同时返回当前容器的上下文
流程:
1.判断当前应用的启动类型(webApplicationType):servlet?reactive?none?
2.加载spring.factories中所有的ApplicationContextInitializer的实现类,存到集合中
3.加载spring.factories中所有的ApplicationListener的实现类,存到集合中
4.推断当前项目的启动main函数:在方法中抛出一个运行时异常,获取异常栈信息中main方法对应的className
启动:
1.记录当前项目的启动耗时
2.加载spring.factories文件中SpringApplicationRunListener的实现类EventPublishingRunListener(在后面,spring会通过多事件派发器来通知所有的事件监听器)
3.发布starting事件
4.发布prepareEnvironment事件:在这里,会获取到spring的配置文件,并按照优先级进行覆盖;该方法主要是完成了将application.properties配置文件配置的内容赋值到spring容器中的作用(优先级的覆盖),最后,会调用MutablePropertySources.addLast()方法
5.根据webApplicationType来创建上下文环境(ConfigurableApplicationContext)
6.刷新容器:在刷新容器中,会调用子类的onRefresh()方法,早onRefresh()方法中初始化dispatcherServlet、启动Tomcat容器
8.发布started事件和running事件
1 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { 2 this.resourceLoader = resourceLoader; 3 Assert.notNull(primarySources, "PrimarySources must not be null"); 4 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); 5 //判断当前应用是什么哪种类型的 none/servlet/reaction 6 this.webApplicationType = WebApplicationType.deduceFromClasspath(); 7 //从META-INF/spring.factories中读取ApplicationContextInitializer的实现类,放到集合中 8 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); 9 //从META-INF/spring.factories中读取ApplicationListener的实现类,放到集合中 10 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); 11 //获取到当前应用的启动函数 main方法 12 this.mainApplicationClass = deduceMainApplicationClass(); 13 }
1 public ConfigurableApplicationContext run(String... args) { 2 //获取时间戳,用来计算启动时间 3 StopWatch stopWatch = new StopWatch(); 4 stopWatch.start(); 5 ConfigurableApplicationContext context = null; 6 Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); 7 configureHeadlessProperty(); 8 /** 9 * 获取spring.factories文件中SpringApplicationRunListener的实现类 10 * 在调用starting的时候,会通过multicastEvent(多事件派发器)发送事件消息,会通知所有的事件监听器,让监听器判断是否对当前发布的事件感兴趣,如果感兴趣,就调用当前监听器的onApplicationEvent()方法 11 * 那是如何判断当前监听器是否对多事件派发器发送的事件感兴趣呢? 12 * supportsSourceType 13 * 和supportsEventType这两个方法 14 */ 15 SpringApplicationRunListeners listeners = getRunListeners(args); 16 listeners.starting(); 17 try { 18 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 19 //发布prepareEnviroment事件,在这个事件中,org.springframework.boot.context.config.ConfigFileApplicationListener#onApplicationEvent会完成spring 20 //boot配置文件优先级的读取和覆盖 21 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); 22 configureIgnoreBeanInfo(environment); 23 Banner printedBanner = printBanner(environment); 24 //初始化容器上下文,根据webApplicationType类型来判断 25 context = createApplicationContext(); 26 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, 27 new Class[] { ConfigurableApplicationContext.class }, context); 28 prepareContext(context, environment, listeners, applicationArguments, printedBanner); 29 //刷新spring容器,在这个方法里面完成了Tomcat的初始化和dispatcherServlet的初始化 30 refreshContext(context); 31 afterRefresh(context, applicationArguments); 32 stopWatch.stop(); 33 if (this.logStartupInfo) { 34 new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); 35 } 36 listeners.started(context); 37 callRunners(context, applicationArguments); 38 } 39 catch (Throwable ex) { 40 handleRunFailure(context, ex, exceptionReporters, listeners); 41 throw new IllegalStateException(ex); 42 } 43 44 try { 45 listeners.running(context); 46 } 47 catch (Throwable ex) { 48 handleRunFailure(context, ex, exceptionReporters, null); 49 throw new IllegalStateException(ex); 50 } 51 return context; 52 }
这个是springboot启动流程的源码,其中有两个点是比较重要的:
1.prepareEnviroment事件的发布(springboot配置文件的解析)
2.刷新spring容器,完成Tomcat的初始化和dispatcherServlet的初始化