IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot 启动过程和自动装配 -> 正文阅读

[Java知识库]SpringBoot 启动过程和自动装配

SpringBoot 启动过程和自动装配

SpringBoot启动过程

  • SpringBoot启动注解了@SpringBootApplication 的 xxxApplication的main方法中,SpringApplication.run(DemoApplication.class, args)这个是启动的开始位置。主要分为两个步骤:
  • 1、SpringApplication初始化META_INF/spring.factories中11个ApplicationListener类型的Listener对象和 7个ApplicationContextInitializer类型的Initializer对象。
  • 2、SpringApplication对象run()方法完成SpringBoot的启动过程。SpringBoot的启动过程有7中状态:ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent、ApplicationPreparedEvent、ApplicationStartedEvent、ApplicationReadyEvent和ApplicationFailedEvent。通过观察者模式,当有状态事件发生时,触发11个ApplicationListener中能够处理的Listener进行事件处理。SpringBoot的启动过程主要分为:1)配置环境变量(系统环境变量、配置文件参数);2)打印启动的banner信息;3)创建webApplicationType类型的Context(SERVLET、REACTIVE、 NONE);4)调用applyInitializers()进行7个ApplicationContextInitializer对象进行初始化添加3个Processor(CachingMetadataReaderFactoryPostProcessor、ConfigurationWarningsPostProcessor、PropertySourceOrderingPostProcessor和Listener添加,以及其他初始化操作,打印starting启动日志,beanFactory load SpringBootApplication的SpringBoot启动类,向beanFactory 注册到beanDefinitionMap中;5)调用spring AbstractApplicationContext refresh进行类的加载
    context进行简单的属性初始化准备下环境;6)打印服务启动的时间的日志。具体流程见图:
    在这里插入图片描述
  • 3启动流程的关键源码:
//在SpringApplication构造函数中初始化

//META_INF/spring.factories中11个ApplicationListener类型的Listenner对象和 7个ApplicationContextInitializer类型的Initializer对象
//# Application Listeners spring-boot
//org.springframework.context.ApplicationListener=\
//org.springframework.boot.ClearCachesApplicationListener,\
//org.springframework.boot.builder.ParentContextCloserApplicationListener,\
//org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
//org.springframework.boot.context.FileEncodingApplicationListener,\
//org.springframework.boot.context.config.AnsiOutputApplicationListener,\
//org.springframework.boot.context.config.ConfigFileApplicationListener,\
//org.springframework.boot.context.config.DelegatingApplicationListener,\
//org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
//org.springframework.boot.context.logging.LoggingApplicationListener,\
//org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
//# Application Listeners spring-boot-autoconfigure
//org.springframework.context.ApplicationListener=\
//org.springframework.boot.autoconfigure.BackgroundPreinitializer

//# 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
//# Initializers
//org.springframework.context.ApplicationContextInitializer=\
//org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
//org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
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();
                setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
                setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
                this.mainApplicationClass = deduceMainApplicationClass();
}

//SpirngBoot的启动流程
public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	//开始计时
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>. ();
	configureHeadlessProperty();
	//加载EventPublishingRunListener,通过观察者模式,SpingBoot的7种状态事件的触发
	SpringApplicationRunListeners listeners = getRunListeners(args);
	
	//ApplicationStartingEvent事件发生
	listeners.starting();
	try {
	   ApplicationArguments applicationArguments = new
	   DefaultApplicationArguments(args);
	   //配置环境变量
	   ConfigurableEnvironment environment = prepareEnvironment(listeners,
	   applicationArguments);
	   configureIgnoreBeanInfo(environment);
	   //打印启动bnnner日志
	   Banner printedBanner = printBanner(environment);
	   
	   //创建webApplicationType类型的Context(SERVLET、REACTIVE、 NONE)
	   context = createApplicationContext();
	   exceptionReporters =
	   getSpringFactoriesInstances(SpringBootExceptionReporter.class,
	   new Class[] { ConfigurableApplicationContext.class }, context);
	   
	   /**调用applyInitializers()进行7个ApplicationContextInitializer对象进行初始化
	   添加3个Processor(CachingMetadataReaderFactoryPostProcessor、
	   ConfigurationWarningsPostProcessor、PropertySourceOrderingPostProcessor和
	   Listener添加,以及其他初始化操作,打印starting启动日志,beanFactory load 
	   SpringBootApplication的SpringBoot启动类,向beanFactory 注册到
	   beanDefinitionMap中;
	   */
	   prepareContext(context, environment, listeners, applicationArguments,
	   printedBanner);
	   //调用spring AbstractApplicationContext refresh进行类的加载
	   //context进行简单的属性初始化准备下环境
	   refreshContext(context);
	   afterRefresh(context, applicationArguments);
	   //启动计时结束打印启动耗时信息
	   stopWatch.stop();
	   if (this.logStartupInfo) {
	         new	     StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(),
	   stopWatch);
	   }
	   //触发ApplicationStartedEvent事件
	  listeners.started(context);
	  callRunners(context, applicationArguments);
	}
     catch (Throwable ex) {
     handleRunFailure(context, ex, exceptionReporters, listeners);
     throw new IllegalStateException(ex);
   }
   try {
       //触发ApplicationReadyEvent
      listeners.running(context);
   }
   catch (Throwable ex) {
       //发生异常,触发失败ApplicationFailedEvent事件
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
   return context;
}

SpringBoot自动装配过程

  • Springboot启动过程主要有完成自动装配关键地方:prepareContext(context, environment, listeners, applicationArguments, printedBanner)和refreshContext(context)中调用PostProcessorRegistrationDelegate中的invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) 方法。prepareContext方法完成SpringBoot项目的xxxApplication的BeanDefinition的注册;refreshContext通过spring的注解扫描完成自动装配。
  • Spring的注解扫描完成自动装配过程中,doProcessConfigurationClass方法完成@ComponentScan、@Import、@PropertySource、@ImportResource和@Bean的扫描,扫描SpringBootApplication会扫描出@SpringBootApplication注解继承过来两个对象:AutoConfigurationImportSelector 和 AutoConfigurationPackages.Registrar。AutoConfigurationImportSelector对象完成从spring.factories文件中加载EnableAutoConfiguration对象。
    在这里插入图片描述
  • 流程中核心代码
//从spring.Factories文件中加载124个EnableAutoConfiguration,并进去条件过去重复的,不需要的EnableAutoConfiguration
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
            AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
         //从spring.Factories文件中加载EnableAutoConfiguration 124个EnableAutoConfiguration
        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
       // 去除重复的
        configurations = removeDuplicates(configurations);
        //去除排除的类
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        //过滤的不用的类
        configurations = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }

//从spring.Factories文件中加载EnableAutoConfiguration
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
                + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 00:56:31  更:2022-09-04 00:57:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:19:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码