【SpringBoot源码】SpringBoot启动流程

SpringBoot启动过程

@SpringBootApplication
public class MySpringApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(MySpringApplication.class, args);
    }
}

SpringBoot工程的启动都是通过SpringApplication.run()方法启动的,包括SpringApplication构造的调用和run()方法的运行。

SpringApplication的构造过程

1.SpringApplication中有段静态代码块:

static {
   Set<String> names = new HashSet<String>();
   // public static final String SERVLET_CONTEXT_PROPERTY_SOURCE_NAME = "servletContextInitParams";
   // public static final String SERVLET_CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams";
   // public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties";
   
   names.add(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME);
   names.add(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME);
   names.add(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME);
   // 将上面三个servlet属性值设置到集合中,unmodifiableSet()方法返回的集合是不可修改的
   SERVLET_ENVIRONMENT_SOURCE_NAMES = Collections.unmodifiableSet(names);
}

2.再初始化logger属性:

private static final Log logger = LogFactory.getLog(SpringApplication.class);

3.执行initialize()方法(有一个重构方法,暂时忽略):

public SpringApplication(Object... sources) {
   initialize(sources);
}

4.initialize()方法执行过程:

// 抑制一下两种告警
@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
   if (sources != null && sources.length > 0) {
      // private final Set<Object> sources = new LinkedHashSet<Object>();
      // sources属性是一个Set,也就是将MySpringApplication.class存入sources
      this.sources.addAll(Arrays.asList(sources));
   }
   // 判断是否时web环境
   this.webEnvironment = deduceWebEnvironment();
   // private List<ApplicationContextInitializer<?>> initializers;
   // 将ApplicationContextInitializer类型的初始化器实例化后存入initializers
   setInitializers((Collection) getSpringFactoriesInstances(
         ApplicationContextInitializer.class));
   // private List<ApplicationListener<?>> listeners;
   // 将ApplicationListener类型的监听器实例化后存入listeners
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   // 找到有main()方法的类(就是也就是将MySpringApplication)存入mainApplicationClass
   this.mainApplicationClass = deduceMainApplicationClass();
}

补充:

  • ApplicationContextInitializer,应用程序初始化器,做一些初始化的工作,也可以通过实现ApplicationContextInitializer接口来自定义初始化器;

  • ApplicationListener,应用程序事件(ApplicationEvent)监听器,SpringBoot提供的监听事件有5个:ApplicationStartedEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent、ApplicationReadyEvent、ApplicationFailedEvent。自定义监听器大致分为三个步骤:

    1.自定义事件:继承自ApplicationEvent抽象类,然后定义自己的构造器;

    2.自定义监听器:实现ApplicationListener接口,然后实现onApplicationEvent方法;

    3.将监听器通过addApplicationListener()注册到Spring应用上下文(ConfigurableApplicationContext);

5.setInitializers()和setListeners()都是调用了getSpringFactoriesInstances()方法:

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
    return getSpringFactoriesInstances(type, new Class<?>[] {});
}

// 实际调用的getSpringFactoriesInstances():
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
		Class<?>[] parameterTypes, Object... args) {
	// 获取线程的classLoader
	ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
	// loadFactoryNames()从默认路径"META-INF/spring.factories"中获取符合type的所有类名全称,并将名字返回一个set集合
	Set<String> names = new LinkedHashSet<String>(
			SpringFactoriesLoader.loadFactoryNames(type, classLoader));
	// createSpringFactoriesInstances()中通过ClassUtils.forName(name, classLoader)方法将所有类实例化返回List
	List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
			classLoader, args, names);
	// 将返回的instances根据配置排序,如@Order(1),因为其继承了OrderComparator类,该类实现了compare()方法,实际时调用了doCompare()方法,实现了通过@Order注解来排序
	AnnotationAwareOrderComparator.sort(instances);
	return instances;
}

SpringApplication run()方法的执行过程

run()方法源码:

public ConfigurableApplicationContext run(String... args) {
   // 实例化一个监视器stopWatch,主要是记录时间和避免重复调用run()方法
   StopWatch stopWatch = new StopWatch();
   // 启动stopWatch,将状态设置为this.running = true;
   stopWatch.start();
   // 创建context,先设为null
   ConfigurableApplicationContext context = null;
   // Headless模式是在缺少显示屏、键盘或者鼠标时的系统配置,this.headless属性默认为true,该方法就是配置该属性
   configureHeadlessProperty();
   // SpringApplicationRunListeners包含log和SpringApplicationRunListener列表两个属性,并继承SpringApplicationRunListener接口包含5个方法:
   // void started();
   // void environmentPrepared(ConfigurableEnvironment environment);
   // void contextPrepared(ConfigurableApplicationContext context);
   // void contextLoaded(ConfigurableApplicationContext context);
   // void finished(ConfigurableApplicationContext context, Throwable exception);
   // 这5个接口方法在SpringApplicationRunListeners类中实现,每个方法都循环通知所有监听器,也即所说的广播
   SpringApplicationRunListeners listeners = getRunListeners(args);
   // 设置了ApplicationStartedEvent事件的监听器会收到事件并执行配置的逻辑
   listeners.started();
   try {
      // 实例化应用参数类
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      // 创建并根据启动时传入的参数更新context
      context = createAndRefreshContext(listeners, applicationArguments);
      // 看下面的afterRefresh源码
      afterRefresh(context, applicationArguments);
      // 广播ApplicationReadyEvent事件,exception参数为null,所以是ApplicationReadyEvent事件
      listeners.finished(context, null);
      // 停止stopWatch,会计算出启动耗时
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
      return context;
   }
   catch (Throwable ex) {
      // 会广播ApplicationFailedEvent事件
      handleRunFailure(context, listeners, ex);
      throw new IllegalStateException(ex);
   }
}

createAndRefreshContext()方法源码:

private ConfigurableApplicationContext createAndRefreshContext(
      SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments) {
   ConfigurableApplicationContext context;
   // 创建并配置环境变量,如果可以get则get,get为null就创建一个
   ConfigurableEnvironment environment = getOrCreateEnvironment();
   // 将args(启动时的参数)设置到environment中
   configureEnvironment(environment, applicationArguments.getSourceArgs());
   // 通知监听器,ApplicationEnvironmentPreparedEvent事件
   listeners.environmentPrepared(environment);
   // 如果不是web环境就跳过if
   if (isWebEnvironment(environment) && !this.webEnvironment) {
      environment = convertToStandardEnvironment(environment);
   }
   // 输出Spring图形启动画面
   if (this.bannerMode != Banner.Mode.OFF) {
      printBanner(environment);
   }

   // Create, load, refresh and run the ApplicationContext
   // 创建context
   context = createApplicationContext();
   // 设置context的environment
   context.setEnvironment(environment);
   // 向context注册beanNameGenerator、resourceLoader、ClassLoader
   postProcessApplicationContext(context);
   // 应用Initializers初始化器
   applyInitializers(context);
   // EventPublishingRunListener发布contextPrepare事件,因为此事件为空,所以此次未做任何操作。
   listeners.contextPrepared(context);
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
   }

   // 把applicationArguments注册到context中,且为单例模式
   context.getBeanFactory().registerSingleton("springApplicationArguments",
         applicationArguments);

   // 加载sources
   Set<Object> sources = getSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   load(context, sources.toArray(new Object[sources.size()]));
   // 发布ApplicationPreparedEvent事件给各个监听器
   listeners.contextLoaded(context);

   // 刷新Spring应用上下文
   refresh(context);
   if (this.registerShutdownHook) {
      try {
         // 注册钩子,避免程序异常关闭资源不释放
         context.registerShutdownHook();
      }
      catch (AccessControlException ex) {
         // Not allowed in some environments.
      }
   }
   return context;
}

createApplicationContext()方法源码:

protected ConfigurableApplicationContext createApplicationContext() {
   Class<?> contextClass = this.applicationContextClass;
   if (contextClass == null) {
      try {
         // 如果是web环境,将org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext实例化给contextClass
         // 如果不是,将org.springframework.context.annotation.AnnotationConfigApplicationContext实例化给contextClass
         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);
}

postProcessApplicationContext()方法源码:

protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
   if (this.webEnvironment) {
      if (context instanceof ConfigurableWebApplicationContext) {
         ConfigurableWebApplicationContext configurableContext = (ConfigurableWebApplicationContext) context;
         if (this.beanNameGenerator != null) {
            // 向context的BeanFactory中注册了beanNameGenerator
            configurableContext.getBeanFactory().registerSingleton(
                  AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
                  this.beanNameGenerator);
         }
      }
   }
   // 如果SpringApplication设置了资源加载器
   if (this.resourceLoader != null) {
      if (context instanceof GenericApplicationContext) {
         // 向context中set了resourceLoader
         ((GenericApplicationContext) context)
               .setResourceLoader(this.resourceLoader);
      }
      if (context instanceof DefaultResourceLoader) {
         // 向context中set了ClassLoader
         ((DefaultResourceLoader) context)
               .setClassLoader(this.resourceLoader.getClassLoader());
      }
   }
}

applyInitializers()方法源码:

protected void applyInitializers(ConfigurableApplicationContext context) {
   // 获取所有的initializer,
   for (ApplicationContextInitializer initializer : getInitializers()) {
      Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
            initializer.getClass(), ApplicationContextInitializer.class);
      Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
      // 不同的初始化器执行各自的initialize()方法执行初始化操作
      initializer.initialize(context);
   }
}

getInitializers()方法源码:

public Set<ApplicationContextInitializer<?>> getInitializers() {
   // 返回不可更改的initializers集合
   return asUnmodifiableOrderedSet(this.initializers);
}

afterRefresh()方法源码:

protected void afterRefresh(ConfigurableApplicationContext context,
      ApplicationArguments args) {
   // 空的,没执行任何操作
   afterRefresh(context, args.getSourceArgs());
   // 调用所有的Runner
   callRunners(context, args);
}

callRunners()方法源码:

private void callRunners(ApplicationContext context, ApplicationArguments args) {
   List<Object> runners = new ArrayList<Object>();
   // 将所有的ApplicationRunner和CommandLineRunner都添加到runners中
   runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
   runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
   // 根据Order接口实现的排序规则排序
   AnnotationAwareOrderComparator.sort(runners);
   // 根据不通的runner类型调用不通的callRunner方法,callRunner方法有两个实现
   for (Object runner : new LinkedHashSet<Object>(runners)) {
      if (runner instanceof ApplicationRunner) {
         callRunner((ApplicationRunner) runner, args);
      }
      if (runner instanceof CommandLineRunner) {
         callRunner((CommandLineRunner) runner, args);
      }
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只努力的微服务

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值