Spring Boot运行阶段

运行阶段是Spring Boot的核心过程,主要围绕public ConfigurableApplicationContext run(String... args) 方法展开,该过程结合初始化阶段完成的状态,进一步完善了运行时所需要的资源,随后启动ApplicationContext上下文,整个流程可分为上下文启动前阶段,上下文装备阶段,上下文启动阶段和上下文启动后阶段。在此期间,触发spring和spring boot的事件,形成完整的SpringApplication的生命周期。run方法源码如下 :

public ConfigurableApplicationContext run(String... args) {
     //秒表
     StopWatch stopWatch = new StopWatch();
     //开始计时
     stopWatch.start();
     //声明Spring上下文
     ConfigurableApplicationContext context = null;
     //异常报告
     Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
     //根据“java.awt.headless”配置Headless,用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true,可以忽略
     configureHeadlessProperty();
     //获取listeners
     SpringApplicationRunListeners listeners = getRunListeners(args);
     //开始监听,EventPublishingRunListener发布ApplicationStartingEvent事件
     listeners.starting();
     try {
         //对args参数的封装,args可以是在命令行中的参数,也可以是在main方法设置的参数
         ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
         //初始化可配置的Environment,EventPublishingRunListener发布ApplicationEnvironmentPreparedEvent事件
         ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
         //得到系统属性spring.beaninfo.ignore,如果为空设置为true
         configureIgnoreBeanInfo(environment);
         //如果未设置banner的mode为off,则输出banner
         Banner printedBanner = printBanner(environment);
         //根据构造函数中的webApplicationType来初始化spring上下文,有WebApplicationContext,ConfigurableWebServerApplicationContext,ConfigurableReactiveWebApplicationContext三种
         context = createApplicationContext();
         //错误分析报告
         exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                                                          new Class[] { ConfigurableApplicationContext.class }, context);
         //准备上下文
         prepareContext(context, environment, listeners, applicationArguments, printedBanner);
         //启动上下文
         refreshContext(context);
         //上下文启动之后的动作,提供给子类扩展
         afterRefresh(context, applicationArguments);
         //结束计时
         stopWatch.stop();
         if (this.logStartupInfo) {
             //打印启动日志,我们经常看到的。。。with PID 17848。。。。就是这里打印的
             new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
         }
         //默认EventPublishingRunListener发布ApplicationStartedEvent事件
         listeners.started(context);
         //从容器中获取ApplicationRunner和CommandLineRunner,并调用其run方法
         callRunners(context, applicationArguments);
     }
     catch (Throwable ex) {
         //异常处理
         handleRunFailure(context, ex, exceptionReporters, listeners);
         throw new IllegalStateException(ex);
     }
 ​
     try {
         //默认EventPublishingRunListener发布ApplicationReadyEvent事件
         listeners.running(context);
     }
     catch (Throwable ex) {
         //异常处理
         handleRunFailure(context, ex, exceptionReporters, null);
         throw new IllegalStateException(ex);
     }
     return context;
 }

 

上下文启动前阶段

StopWatch

秒表,用来计时,类似实现有apache commons和guava,调用了start方法,在下一次调用start方法或前必须保证其stop方法被调用,否则抛出IllegalStateException异常

 

SpringBootExceptionReporter

使用SpringFactoriesLoader.loadFactoryNames加载META-INF/spring.factories中的SpringBootExceptionReporter,默认实现仅FailureAnalyzers,ConfigurableApplicationContext为其构造函数参数。FailureAnalyzers组合模式List<FailureAnalyzer> analyzers,而FailureAnalyzer的实现依然通过SpringFactoriesLoader.loadFactoryNames实现,默认实现如下:

 org.springframework.boot.diagnostics.FailureAnalyzer=\
 org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
 org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer



当我们在实现自己的starter的时候,可以自定义FailureAnalyzer实现,从而引导使用人员正确使用其starter

 

SpringApplicationRunListeners

同样使用组合模式,将构造函数中加载的listeners放入其类型为List<SpringApplicationRunListener> 的listeners字段中,默认实现仅EventPublishingRunListener。EventPublishingRunListener不仅能监听spring boot定义的事件,同样也监听spring的事件,当其contextLoaded(ConfigurableApplicationContext context)方法被调用时,将其listeners增加到了spring的ConfigurableApplicationContext的applicationListeners属性中。

contextLoaded(ConfigurableApplicationContext context)方法源码如下:

 @Override
 public void contextLoaded(ConfigurableApplicationContext context) {
     for (ApplicationListener<?> listener : this.application.getListeners()) {
         if (listener instanceof ApplicationContextAware) {
             ((ApplicationContextAware) listener).setApplicationContext(context);
         }
         context.addApplicationListener(listener);
     }
     this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
 }

而contextLoader方法是其run方法中的准备上下文prepareContext方法中调用的

 

上下文准备阶段

该阶段由prepareContext方法完成,在该方法中,EventPublishingRunListener发布ApplicationContextInitializedEvent事件和ApplicationPreparedEvent事件

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment     
     environment, SpringApplicationRunListeners listeners, ApplicationArguments 
     applicationArguments, Banner printedBanner) {
	//设置environment,有三种实现,spring的StandardEnvironment和StandardServletEnvironment,Spring boot的StandardReactiveWebEnvironment,三者并无多大区别
    context.setEnvironment(environment);
    //spring应用上下文后置处理,子类可以覆盖该实现
    postProcessApplicationContext(context);
    //应用spring上下文初始化器,迭代执行ApplicationContextInitializer的集合
	applyInitializers(context);
    //EventPublishingRunListener发布ApplicationContextInitializedEvent事件
    listeners.contextPrepared(context);
	if (this.logStartupInfo) {
	    logStartupInfo(context.getParent() == null);
          //主要打印profiles相关日志
		logStartupProfileInfo(context);
    }
		// Add boot specific singleton beans
	ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    //注册单例applicationArguments,可通过Autowire自动注入
	beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
   if (printedBanner != null) {
            //注册单例printedBanner
		beanFactory.registerSingleton("springBootBanner", printedBanner);
   }
  if (beanFactory instanceof DefaultListableBeanFactory) {
      //当注册多个相同name的bean时,是否可覆盖,默认false,可通过SpringApplication的实例设置false
      ((DefaultListableBeanFactory) beanFactory)
					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  }
		
   //合并Spring上下文配置源并去重
   Set<Object> sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   //加载spring上下文配置源,将spring上下文Bean的装载任务交给了BeanDefinitionLoader
   load(context, sources.toArray(new Object[0]));
   //EventPublishingRunListener发布ApplicationPreparedEvent事件
   listeners.contextLoaded(context);
}

上下文启动阶段

该阶段由refreshContext(ConfigurableApplicationContext context)方法执行完成,源码如下

 private void refreshContext(ConfigurableApplicationContext context) {
     //启动容器
     refresh(context);
     if (this.registerShutdownHook) {
         try {
             //注册shutdownHoot线程,实现Spring bean销毁生命周期的回调
             context.registerShutdownHook();
         }
         catch (AccessControlException ex) {
             // Not allowed in some environments.
         }
     }
 }

首选调用refresh(ApplicationContext applicationContext)方法,在refresh方法内部,调用AbstractApplicationContext的refresh()方法执行ApplicationContext的启动。

 

上下文启动后阶段

afterRefresh(context, applicationArguments)方法是一个protected修饰的空方法,提供给子类扩展。

listeners.started(context)方法,默认逻辑只有EventPublishingRunListener发布ApplicationStartedEvent事件。

callRunners(context, applicationArguments)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值