SpringBoot启动流程

SpringBoot项目启动方式:

  1. 在IDE中启动SpringBoot主类(XXXApplication)中的main方法
  2. 使用mvn spring-boot:run命令启动
  3. 打成jar包之后使用java -jar xxx.jar运行
  4. 打成war包之后放在web容器中运行

 

SpringBoot启动流程主要分为三步:

第一部分:SpringApplication初始化模块,配置一些基本的环境变量,资源,监听器,构造器;

第二部分:实现了应用具体的启动方案,包括流程的监听模块,加载配置环境模块以及创建上下文环境模块

第三部分:自动化配置模块,这个模块是实现SpringBoot的自动配置

 

SpringBoot程序的主入口就是标注了@SpringBootApplication注解的类,该类中有一个main方法,在main方法中调用SpringApplication的run()方法,这个run()方法来启动整个程序

下面是@SpringBootApplication注解的部分源码

这是一个组合注解,其中标注的注解主要有以下作用

@EnableAutoConfiguration: 开启SpringBoot自动配置,在程序启动时会自动加载SpringBoot的默认配置,如果有对一些参数进行配置,则会在程序启动时或调用时进行追加或者覆盖

@SpringBootConfiguration: 这个注解和@Configuration注解的作用一样,用来表示被标注的类是一个配置类,会将被标注的类中一个或多个被@Bean注解修饰的方法添加到Spring容器中,实例的名字默认是方法名

@ComponentScan: 包扫描注解,默认扫描主类包路径下的类

 

进入run()方法后的代码如下:

这里会创建一个SpringApplication类的实例,进入SpringApplication类中可以看到构造方法里调用了一个initialize(sources)方法

Initialize(sources)方法源码如下:

@SuppressWarnings({ "unchecked", "rawtypes" })
	private void initialize(Object[] sources) {
		if (sources != null && sources.length > 0) {
			//将sources设置到SpringApplication类的source属性中,这时的source值只有主类
			this.sources.addAll(Arrays.asList(sources));
		}
		//判断是不是web程序,
		this.webEnvironment = deduceWebEnvironment();
		//从spring.factories文件中找出key为ApplicationContextInitializer的类进行实例化,然后设置到SpringApplciation类的initializers属性中,这个过程也是找出所有的应用程序初始化器
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
        //从spring.factories文件中找出key为ApplicationListener的类并实例化后设置到SpringApplication的listeners属性中。这个过程就是找出所有的应用程序事件监听器
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //找出main类,也就是SpringBoot项目的主类
		this.mainApplicationClass = deduceMainApplicationClass();
	}

 

执行完初始化之后回到run()方法中,完整代码如下:application, creating and refreshin

**
 * 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) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   FailureAnalyzers analyzers = null;
   configureHeadlessProperty();
   SpringApplicationRunListeners listeners = getRunListeners(args);
   listeners.starting();
   try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
      Banner printedBanner = printBanner(environment);
      context = createApplicationContext();
      analyzers = new FailureAnalyzers(context);
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}

 

在这个方法中主要做了以下几件事,创建应用监听器SpringApplicationRunListeners并且开始监听,

加载SpringBoot配置环境ConfigurableEnvironment

在加载配置环境的过程中会判断是否是web容器启动,如果是容器启动会加载StandardServletEnvironment

StandardServletEnvironment类的继承关系如下,StandardServletEnvironment

PropertyResolver接口是用于解析任何基础源的属性的接口,在加载完配置之后会将配置环境加入到监听器对象SpringApplicationRunListeners中。

然后会创建应用上下文对象,具体代码如下:

 

protected ConfigurableApplicationContext createApplicationContext() {
   Class<?> contextClass = this.applicationContextClass;
   if (contextClass == null) {
      try {
         contextClass = Class.forName(this.webEnvironment
               ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
      }
      catch (ClassNotFoundException ex) {
         throw new IllegalStateException(
               "Unable create a default ApplicationContext, "
                     + "please specify an ApplicationContextClass",
               ex);
      }
   }
   return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}

方法会先显式的获取应用上下文对象,如果对象为空,再加载默认的环境配置,通过是否是webEnvironment进行判断,默认选择的是AnnotationConfigApplicationContext(注解上下文,通过扫秒注解来加载bean),然后通过BeanUtils来实例化应用上下文对象然后返回,ConfigurableApplicationContext类继承关系如下

回到run()方法中,会调用prepareContext()方法将environment, listeners,applicationArguments, printedBanner等组件与上下文对象进行关联

然后会调用refreshContext()方法,实际调用org.springframework.context.support.AbstractApplicationContext.refresh()内的相关方法。这个方法里会进行redis,mybatis等的自动配置,包括spring.factories的加载,bean的实例化,BenFactoryPostProcessor接口的执行,BeanPostProcessor接口的执行,条件注解的解析,国际化功能的初始化等。

refreshContext()方法执行完毕之后会执行afterRefresh方法,当run()方法执行完之后Spring容器也就初始化完毕了

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值