SpringBoot从宏观上说,就是对spring容器进行了一层包装。它内部的入口是利用 SpringApplication类的static的 run 方法进行启动的,调用的图:

  

上图中的这些方法都位于org.springframework.boot.SpringApplication这个类中,由此可见SpringApplication这个类在springboot框架中的作用。

//调用示例:

public static void main(String[] args) throws Exception {
  SpringApplication.run(Examples.class, args);
}

SpringApplication类提供了两个static的run方法:

public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[] { source }, args);
} public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}

上面两个方法其实就是一个,最终都会创建一个SringApplication实例,在构造时会处理传入的 sources 参数,而且这souces类可以是多个,调用的方式还可以这样:

public static void main(String[] args) throws Exception {

  Class<?>[] primarySources = new Class<?>[] { Examples.class , Examples1.class } ;
  SpringApplication.run( primarySources , args);
}

SpringApplication构造方法如下:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  this.resourceLoader = resourceLoader;
  Assert.notNull(primarySources, "PrimarySources must not be null");
  this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  this.webApplicationType = WebApplicationType.deduceFromClasspath();   //用来查找每个jar和类路径下的/META-INF/spring.factories文件,并获取其中的特定接口的配置的
  setInitializers((Collection) getSpringFactoriesInstances(
  ApplicationContextInitializer.class)); //找出每个jar和类路径下的/META-INF/spring.factories文件中配置的ApplicationContextInitializer类
  setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));   this.mainApplicationClass = deduceMainApplicationClass(); //推断出带有main方法的运行类
}

上面的代码通过构造完成初始化之后,紧接着就是调用SpringApplication类的实例 run方法,代码如下:

public ConfigurableApplicationContext run(String... args) {
//StopWatch作用是用来统计spring实例运行时间
StopWatch stopWatch = new StopWatch();
stopWatch.start(); //ConfigurableApplicationContext接口提供了对Spring容器的配置功能
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 1. 会执行ApplicationContextInitializer接口进行初始化工作
// 2. 对外发布监听事件
// 3. 优先创建有特定作用的单例bean
// 4. 把带有main方法的主类作为bean的配置源,并从配置源中加载bean信息到容器中
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//spring容器的生命周期处理,该方法完成后单例bean实例就创建了
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
//对外发布监听事件
listeners.started(context);
//我们在开发中可能会有这样的情景。需要在容器启动的时候执行一些内容。比如读取配置文件,数据库连接之类的。SpringBoot给我们提供了两个接口来帮助我们实现这种需求。这两个接口分别为CommandLineRunner和ApplicationRunner。他们的执行时机为容器启动完成的时候。
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
} try {
//发布监听事件
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}

至此,SpringApplication的实例run方法执行完成,该方法主要是完成spring容器的创建和启动

2. Spring Boot项目启动原理初探的更多相关文章

  1. 让Spring Boot项目启动时可以根据自定义配置决定初始化哪些Bean

    让Spring Boot项目启动时可以根据自定义配置决定初始化哪些Bean 问题描述 实现思路 思路一 [不符合要求] 思路二[满足要求] 思路三[未试验] 问题描述 目前我工作环境下,后端主要的框架 ...

  2. spring boot 项目启动无任何反应

    遇到的问题 spring boot项目启动后无任何报错,ps有进程,nohub无日志 定位 更换jar包,问题依然存在,将jar包放到其他服务器,运行正常,排除打包问题 同服务器其他系统运行正常,但停 ...

  3. spring boot应用启动原理分析

    spring boot quick start 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个We ...

  4. Spring Boot应用启动原理分析(转)

    在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web Server. 如果之前没有使用过sprin ...

  5. spring boot项目启动报DataSource错误

    初建一个简单的spring boot 项目,启动后会报错. Exception encountered during context initialization - cancelling refre ...

  6. 创建spring boot项目启动报错遇到的问题

    1.Spring boot,Mybatis 启动报错 Failed to auto-configure a DataSource *************************** APPLICA ...

  7. spring boot项目启动报(No session repository could be auto-configured, check your configuration (session store type is 'null'))

    找到项目的application配置文件,增加 spring.session.store-type=none,重新启动问题解决 注:因为项目未使用redis管理session,可以如上设置,如果想使用 ...

  8. spring boot 项目启动无法访问,排查

    查看docker日志,后台应用正常启动,定时任务正常执行,但是前端无法访问到后端接口,点击提示系统错误,解压出项目二级域名,访问域名,报错:Kong Error,说明Kong路由转发没有绑定项目端口, ...

  9. spring boot项目启动报错

    在eclipse中运行没有任何问题,项目挪到idea之后就报错 Unable to start EmbeddedWebApplicationContext due to miss EmbeddedSe ...

随机推荐

  1. Hbase学习03

    第3章 Hbase数据存储模型与工作组件 Data格式设计的的总体原则是按照需求要求,依据Hbase性能的相关标准规范和文件,并遵循“统一规范.统一数据模型.统一规划集群.分步实施”的原则,注重实际应 ...

  2. nginx做负载均衡+keepalived(做主备)

    部署Nginx 一,安装nginx依赖: 查看是否已经安装 rpm -qa |grep gcc rpm -qa |grep openssl-devel rpm -qa |grep pcre-devel ...

  3. Hadoop记录-技术网站

    Grafan监控:http://docs.grafana.org/ Tez:http://tez.apache.org/install.html 阿里巴巴镜像:https://opsx.alibaba ...

  4. SQL记录-ORACLE 12C初体验

    1.部署 2.使用

  5. golang反射举例

    反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:并且能改变它的属性. package main import ( "f ...

  6. js工具库

    js-md5:https://www.npmjs.com/package/js-md5

  7. MySQL的随笔

    数据库引擎 MySQL5.0支持的存储引擎包括MyISAM,InnoDB.MEMORY.MERGE.BDB等等,其中InnoDB和BDB提供事务安全表,其他存储引擎都是非事务安全表. MyISAM M ...

  8. consul - 基础

    =============================consul 是什么============================= consul 是 HashiCorp 公司推出的开源工具, 该 ...

  9. Android上禁止屏幕旋转

    看网上讲了很多,设置很多属性,设置了很多,其实最关键的一点是这个 @Overrideprotected void onResume() { /** * 设置为横屏 */ if(getRequested ...

  10. ext Table中CommandColumn用法

    <ext:CommandColumn Width="250" Header="功能菜单" ColumnID="test"  Butto ...