栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Boot启动原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot启动原理

Spring Boot启动原理

Spring Boot版本为2.6.0

一、从main函数开始
public static void main(String[] args) {
    SpringApplication.run(SpringBootDemoApplication.class, args);
}

SpringApplication的静态run方法

public static ConfigurableApplicationContext run(Class primarySource, String... args) {
   return run(new Class[] { primarySource }, args);
}
​
public static ConfigurableApplicationContext run(Class[] primarySources, String[] args) {
    // 新建一个SpringApplicaton实例,先执行构造函数然后在执行非静态的run方法。
   return new SpringApplication(primarySources).run(args);
}

新建一个SpringApplicaton实例,先执行构造函数,然后在执行非静态的run方法。

二、SpringApplication的构造方法

SpringApplication的构造方法进行的一系列操作

  • 设置类装载器

  • 设置引导程序注册的初始化器

  • 设置容器的初始化类器

  • 设置监听器类实例

public SpringApplication(Class... primarySources) {
        this(null, primarySources);
}
​
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();
   
   this.bootstrapRegistryInitializers = new ArrayList<>(
         getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
   
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   // 根据Java虚拟机栈的入栈的方法寻找main方法,返回main方法的class对象
   this.mainApplicationClass = deduceMainApplicationClass();
}

spring.factories文件内容(spring-boot-2.6.0.jar包meta-INF目录下的,其他spring-boot-xxx.jar包也有)

# Logging Systems
org.springframework.boot.logging.LoggingSystemFactory=
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,
org.springframework.boot.logging.java.JavaLoggingSystem.Factory
​
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=
org.springframework.boot.env.PropertiesPropertySourceLoader,
org.springframework.boot.env.YamlPropertySourceLoader
​
# ConfigData Location Resolvers
org.springframework.boot.context.config.ConfigDataLocationResolver=
org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,
org.springframework.boot.context.config.StandardConfigDataLocationResolver
​
# ConfigData Loaders
org.springframework.boot.context.config.ConfigDataLoader=
org.springframework.boot.context.config.ConfigTreeConfigDataLoader,
org.springframework.boot.context.config.StandardConfigDataLoader
​
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=
org.springframework.boot.context.event.EventPublishingRunListener
​
# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=
org.springframework.boot.diagnostics.FailureAnalyzers
​
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,
org.springframework.boot.context.ContextIdApplicationContextInitializer,
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
​
# Application Listeners
org.springframework.context.ApplicationListener=
org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.context.logging.LoggingApplicationListener,
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
​
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,
org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
​
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=
org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer,
org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer,
org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,
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.MutuallyExclusiveConfigurationPropertiesFailureAnalyzer,
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,
org.springframework.boot.diagnostics.analyzer.PatternParseFailureAnalyzer,
org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer
​
# Failure Analysis Reporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
​
# Database Initializer Detectors
org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector=
org.springframework.boot.flyway.FlywayDatabaseInitializerDetector,
org.springframework.boot.jdbc.AbstractDataSourceInitializerDatabaseInitializerDetector,
org.springframework.boot.jdbc.init.DataSourcescriptDatabaseInitializerDetector,
org.springframework.boot.liquibase.LiquibaseDatabaseInitializerDetector,
org.springframework.boot.orm.jpa.JpaDatabaseInitializerDetector,
org.springframework.boot.r2dbc.init.R2dbcscriptDatabaseInitializerDetector
​
# Depends On Database Initialization Detectors
org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector=
org.springframework.boot.sql.init.dependency.AnnotationDependsOnDatabaseInitializationDetector,
org.springframework.boot.jdbc.SpringJdbcDependsOnDatabaseInitializationDetector,
org.springframework.boot.jooq.JooqDependsOnDatabaseInitializationDetector,
org.springframework.boot.orm.jpa.JpaDependsOnDatabaseInitializationDetector
三、SpringApplication实例的run()方法(非静态run方法)
public ConfigurableApplicationContext run(String... args) {
   // 开始计时:返回正在运行的Java虚拟机的当前值 
   long startTime = System.nanoTime();
   
   DefaultBootstrapContext bootstrapContext = createBootstrapContext();
   ConfigurableApplicationContext context = null;
   
   configureHeadlessProperty();
   
   SpringApplicationRunListeners listeners = getRunListeners(args);
   
   listeners.starting(bootstrapContext, this.mainApplicationClass);
   try {
       
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
       
      ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
      
      configureIgnoreBeanInfo(environment);
      
      Banner printedBanner = printBanner(environment);
      
      context = createApplicationContext();
      
      context.setApplicationStartup(this.applicationStartup);
      
      prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
      
      refreshContext(context);
      
      afterRefresh(context, applicationArguments);
      Duration timetakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timetakenToStartup);
      }
      // 监听器启动
      listeners.started(context, timetakenToStartup);
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, listeners);
      throw new IllegalStateException(ex);
   }
   try {
      Duration timetakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
      // 监听器开始工作
      listeners.ready(context, timetakenToReady);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, null);
      throw new IllegalStateException(ex);
   }
   return context;
}
四、SpringApplication实例的prepareContext()方法
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
   // 设置配置环境
   context.setEnvironment(environment);
   // 后置处理应用上下文
   postProcessApplicationContext(context);
   
   applyInitializers(context);
   // 会按优先级顺序遍历执行SpringApplicationRunListener的contextPrepared方法
   listeners.contextPrepared(context);
   // 关闭bootstrapContext
   bootstrapContext.close(context);
   if (this.logStartupInfo) {
      // 启动信息输出到控制台
      logStartupInfo(context.getParent() == null);
      // 活动配置文件信息输出到控制台
      logStartupProfileInfo(context);
   }
   // Add boot specific singleton beans
   // 获取应用上下文的内部bean工厂
   ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
   // applicationArguments注册为单例,bean的ID为springApplicationArguments
   beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
   if (printedBanner != null) {
      // printedBanner注册为单例,bean的ID为springBootBanner
      beanFactory.registerSingleton("springBootBanner", printedBanner);
   }
   if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
      ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
      if (beanFactory instanceof DefaultListableBeanFactory) {
          // 设置bean定义信息是否允许覆盖,this.allowBeanDefinitionOverriding默认为false
         ((DefaultListableBeanFactory) beanFactory)
               .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
      }
   }
   // 根据this.lazyInitialization布尔值,是否添加懒加载bean工厂后置处理器
   if (this.lazyInitialization) {
      context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
   }
   // Load the sources
   // 获取bean,为SpringApplication.run(SpringBootShiroApplication.class, args)中这里传的class
   Set sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   // 为容器加载bean
   load(context, sources.toArray(new Object[0]));
   // 通知监听器们,容器加载完成。
   // 在加载应用程序上下文之后,但在刷新之前调用它。 
   listeners.contextLoaded(context);
} 
五、SpringApplication实例的refreshContext()方法 
private void refreshContext(ConfigurableApplicationContext context) {
   if (this.registerShutdownHook) {
      // 一个Runnable,用作一个关闭钩子,用于优雅地关闭Spring Boot应用程序
      shutdownHook.registerApplicationContext(context);
   }
   refresh(context);
}

以下是调用AbstractApplicationContext类的refresh()方法

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
​
      
      prepareRefresh();
​
      // 获取刷新后的bean工厂
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
​
      // 准备bean工厂,配置bean工厂属性
      prepareBeanFactory(beanFactory);
​
      try {
         // 设置bean工厂的后置处理
         postProcessBeanFactory(beanFactory);
         // 开始ng.context.beans.post-process步骤
         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         // 调用在上下文中注册为bean工厂后置处理器
         invokeBeanFactoryPostProcessors(beanFactory);
​
         // 注册拦截bean创建的bean后置处理器
         registerBeanPostProcessors(beanFactory);
         // spring.context.beans.post-process步骤结束
         beanPostProcess.end();
​
         // 初始化MessageSource,国际化处理
         initMessageSource();
​
         // 初始化事件
         initApplicationEventMulticaster();
​
         // Initialize other special beans in specific context subclasses.
         onRefresh();
​
         // 注册监听器们
         registerListeners();
​
         // 完成此上下文的bean工厂的初始化,初始化所有剩余的单例bean。  
         finishBeanFactoryInitialization(beanFactory);
​
         
         finishRefresh();
      }
​
      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }
​
         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();
​
         // Reset 'active' flag.
         cancelRefresh(ex);
​
         // Propagate exception to caller.
         throw ex;
      }
​
      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();// 重置缓存
         contextRefresh.end();
      }
   }
}

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号