精华内容
下载资源
问答
  • springboot启动流程图.rp

    2020-06-01 16:44:51
    使用Axure画的Springboot启动流程图源文件《springboot启动流程图.rp》,可以下载编辑。导出的图片,请查看博客:https://blog.csdn.net/axin1240101543/article/details/106475798
  • Springboot介绍 Springboot并不是一个新的功能框架,...Springboot启动离不开@SpringBootApplication注解,它为SpringApplication上下文的各类Bean加载提供了很大的支持 @SpringBootApplication注解 @SpringBootApplic

    Springboot介绍

    Springboot并不是一个新的功能框架,而是Spring的一个子项目框架,它提供了自动装配的功能,简化了使用Spring框架的各种繁琐配置,而且集成了大部分主流组件配置.做到了Spring的开箱即用.

    Springboot启动

    Springboot启动离不开@SpringBootApplication注解,它为SpringApplication上下文的各类Bean加载提供了很大的支持

    @SpringBootApplication注解

    @SpringBootApplication注解在Springboot项目启动类上,是Springboot启动非常重要的部分.它主要由三个核心注解集成,为其提供核心功能该注解加载Bean至容器中发生于run方法的上下文准备完成后的刷新上下文过程中(this.refreshContext(context))
    在这里插入图片描述
    在这里插入图片描述

    1. @SpringBootConfiguration

    该注解集成@Configuration,表示该类为配置类,它也会被加载至容器中进行管理

    2. @EnableAutoConfiguration(开启Springboot自动装配机制)

    1. 该类由@AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class})集成
    2. @AutoConfigurationPackage注解又集成了@Import({Registrar.class})注解,它负责加载当前包路径下所有的@Configuration配置Bean.该注解加载Bean至容器中发生于run方法的上下文准备完成后的刷新上下文过程中(this.refreshContext(context))
    //它是AutoConfigurationPackages抽象类的内部类
    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }
    
        //注册Bean方法
        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            //这一步的getPackageNames()方法获取当前包路径用以进行自动包配置Bean的注册.它是拿的当前注解的一些元数据包括当前的包名
            AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }
    
        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
        }
    }
    

    1. @Import({AutoConfigurationImportSelector.class})其加载了依赖的各个组件resource下/MEAT-INF/spring.factoriesorg.springframework.boot.autoconfigure.EnableAutoConfiguration指定的所有配置Bean.该注解加载Bean至容器中发生于run方法的上下文准备完成后的刷新上下文过程中(this.refreshContext(context)). 可参考spring-boot-autoconfigure依赖下的spring.factories文件.
    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            // 获取所有配置文件中配置的配置类名
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.getConfigurationClassFilter().filter(configurations);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }
    
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        // 从spring.factories文件中获取EnableAutoConfiguration键指定的自动配置类列表(需加@Configuration注解). SpringFactoriesLoader.loadFactoryNames方法将在Springboot启动过程中多次用到
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
    }
    

    3. @ComponentScan

    @ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM,classes ={TypeExcludeFilter.class}), 
    @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class})
    })
    

    该注解主要用来扫描@Component及其集成它的类装配到容器中(默认启动类包路径下).例如@Controller、@Service、@Repository等Bean声明注解.

    SpringApplication启动

    讲完@SpringBootApplication注解就要讲启动了,其启动又分为实例化和run方法执行

    1. SpringApplication类实例化

    传入基类构造SpringApplication实例

    1. 保存基类至SpringApplication基类属性(PrimarySources集合)中
    2. 设置该应用类型是响应式REACTIVE的还是Web应用SERVLET(判断有没有DispatcherServlet )
    3. 加载上下文初始化器ApplicationContextInitializer集合 —> 从spring.factories中读取设置全局启动上下文初始化器(实现ApplicationContextInitializer.class类的)
    4. 加载监听器ApplicationListener集合 —> 从spring.factories中读取设置的监听器(实现ApplicationListener.class类的)
    上面的设置用到下面方法
    setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class))
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class))
    
    主要使用SpringFactoriesLoader.loadFactoryNames(Class<?> factoryType, ClassLoader classLoader)方法,通过读取spring.factories中设置的符合定义类名集合来进行加载实例化
    

    SpringApplication.run(String …args)方法构造Application上下文

    该run方法内部主要实现了运行环境配置以及SpringApplication上下文的装载准备.并在不同的阶段发布不同的事件以进行服务启动前的一些配置准备工作

    1. 获取SpringApplicationRunListeners监听器列表(默认有EventPublishingRunListener,在启动不同阶段发布不同的启动事件).可在spring.factories添加自定义启动监听器(实现SpringApplicationRunListener.class类).
    2. 执行监听器列表的starting方法,默认发布启动事件listeners.starting()(ApplicationStartingEvent)
    3. 初始化应用环境,并且监听器列表发布环境准备完毕事件listeners.environmentPrepared()(ApplicationEnvironmentPreparedEvent),并且在这一步读取了bootstrap和application配置文件配置
    4. 实例化并打印Banner
    5. 创建应用上下文ConfigurableApplicationContext,为上下文配置环境参数、执行初始化器.发布上下文初始化完毕事件listeners.contextPrepared(context)(ApplicationContextInitializedEvent).
    6. 给Bean工厂加入一些启动过程中产生的单例Bean,设置上下文Bean是否懒加载,加入根启动类Bean.发布上下文准备完毕事件listeners.contextLoaded(context)(ApplicationPreparedEvent,这一步也进行了bootstrap和application配置读取)
    7. 刷新上下文refreshContext(context),执行大名鼎鼎的refresh()方法
    8. 执行刷新后处理方法afterRefresh,这一步啥都没有做,方法体是空的,可以继承自定义
    9. 监听器发布启动完毕监听事件listeners.started(context)(ApplicationStartedEvent)
    10. 执行配置的ApplicationRunner和CommandLineRunner(可实现该两个接口并使用注解注入Bean即可.此时上下文已经加载好了.只在这时执行一次)
    11. 最后发布运行事件listeners.running(context)(ApplicationReadyEvent)

    上述事件的监听器自定义可通过spring.factoriesorg.springframework.context.ApplicationListener= 指定自定义的监听器全路径地址 org.springframework.boot.SpringApplicationRunListener=应用启动监听器配置.这些事件监听器均不能使用注入Bean的方式获取实例,可以通过从上下文的BeanFactory获取

    // run方法
    public ConfigurableApplicationContext run(String... args) {
    	StopWatch stopWatch = new StopWatch();
    	stopWatch.start();
    	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);
    		stopWatch.stop();
    		if (this.logStartupInfo) {
    			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
    		}
    		listeners.started(context);
    		callRunners(context, applicationArguments);
    	}
    	catch (Throwable ex) {
    		handleRunFailure(context, ex, listeners);
    		throw new IllegalStateException(ex);
    	}
    
    	try {
    		listeners.running(context);
    	}
    	catch (Throwable ex) {
    		handleRunFailure(context, ex, null);
    		throw new IllegalStateException(ex);
    	}
    	return context;
    }
    
    

    如有错误还请各位大佬不吝赐教

    展开全文
  • 主要介绍了SpringBoot启动及自动装配原理过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • SpringBoot启动流程

    2021-01-31 15:48:20
    1 SpringBoot启动流程 该图描述了SpringBoot启动过程中所需要的大致流程,链接地址:https://upload-images.jianshu.io/upload_images/6912735-51aa162747fcdc3d.png?imageMogr2/auto-orient/strip 1.1 ...

    1 SpringBoot启动流程 返回目录

    (本文基于SpringBoot 2.1.x分析。)

    该图描述了SpringBoot启动过程中所需要的大致流程,链接地址:https://upload-images.jianshu.io/upload_images/6912735-51aa162747fcdc3d.png?imageMogr2/auto-orient/strip
    在这里插入图片描述

    1.1 SpringApplication构造方法初始化

    1.1.1 SpringBoot应用类型推断

    SpringBoot2.0 支持响应式编程,因此为了能够区分不同的应用,SpringBoot通过枚举WebApplicationType来区分应用类型,便于在启动Spring时选用合适的ConfigurableApplicationContext实现。

    1. REACTIVE: 类路径存在org.springframework.web.reactive.DispatcherHandler但不存在servlet.DispatcherServletorg.glassfish.jersey.servlet.ServletContainer
    2. SERVLET: 当javax.servlet.ServletConfigurableWebApplicationContext同时在则认为时web应用类型
    3. NONE: 表示普通应用类型

    1.1.2 从spring.factories文件加载初始化器和监听器

    Spring通过工具类SpringFactoriesLoader从classpath扫描所有jar包中的META-INF/spring.factories配置文件,读取spring.factoies中的配置类信息,保存在MultiValueMap<String, String>中,key为接口全类名,value为实现类全类名.一个key可以对应多个实现类.该工具类主要有两个方法:

    1. List<T> loadFactories(factoryClass, classLoader)返回排序后的对象集合
    2. List<String> loadFactoryNames(factoryClass, classLoader) 在SpringApplication构造方法中会分别读取org.springframework.context.ApplicationContextInitializerorg.springframework.context.ApplicationListener两个接口实现类对象集合。 ApplicationContextInitializer用于在上下文ApplicationContext创建后回调。而ApplicationListener则用于监听SpringBoot在整个启动过程中监听相应的事件.

    默认情况下ApplicationContextInitializer实现类有如下:

    1. org...boot.context.config.DelegatingApplicationContextInitializer
      用于解析通过属性context.initializer.classes指定的ApplicationContextInitializer实现类,并调用其实现的接口方法
    1. org...boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer
      通过applicationContext.addBeanFactoryPostProcessor(…)注册CachingMetadataReaderFactoryPostProcessorBeanFactoryPostProcessor中文翻译后置处理器,这是Spring生命周期中最重要的回调接口,工厂模式获取MetadataReader用于读取class文件信息.相关类: ClassMetadata, SimpleMetadataReader
    2. org...boot.context.ContextIdApplicationContextInitializer
      读取spring.application.name属性值,默认为application,做为ConfigurableApplicationContextid
    3. org...boot.context.ConfigurationWarningsApplicationContextInitializer
      用于验证设置的包名是否包含org.springframeworkorg,如果包含则输出警告日志,不过只是验证了@ComponentScan注解(包含@SpringBootApplication继承的),但是没有验证@ComponentScans注解
    4. org...boot.web.context.ServerPortInfoApplicationContextInitializer
      用于web环境下读取设置服务端端口
    5. org...boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
      当Spring中条件注解验证不通过时打印日志,仅当debug级别打印,SpringBoot默认为info级别.

    ApplicationListener实现类如下:

    1. org...boot.context.config.ConfigFileApplicationListener
      用于读取application.yml, application.properties配置文件,并解析spring.profiles.active指定的配置文件.
    2. org...boot.context.config.AnsiOutputApplicationListener
      用于控制是否在控制台打印彩色日志
    3. org...boot.context.logging.LoggingApplicationListener
      用于日志初始化,在LoggingApplicationListener监听的ApplicationEnvironmentPreparedEvent事件执行之前日志不可用
    4. org...boot.context.logging.ClasspathLoggingApplicationListener
      打印当前项目启动的类路径信息,所加载的jar信息
    5. org.springframework.boot.autoconfigure.BackgroundPreinitializer
      SpringBoot启动过程唯一用到多线程的地方,用于触发一些类静态块的执行,减少启动耗时
    6. org...boot.context.config.DelegatingApplicationListener
      DelegatingApplicationListener监听到ApplicationEnvironmentPreparedEvent事件时,解析属性context.listener.classes配置的监听器并发布事件,因此context.listener.classes配置的事件监听器只能监听 ApplicationEnvironmentPreparedEvent以及之后的事件,无法监听ApplicationStartedEvent事件。
    7. org...boot.ClearCachesApplicationListener
      监听ContextRefreshedEvent事件,清除ClassLoader缓存
    8. org...boot.context.FileEncodingApplicationListener
      验证开发者配置的属性spring.mandatory-file-encoding值和System.getProperty("file.encoding")获取的值是否一致,如果不一致则打印错误日志,如果没有设置则不验证.

    1.1.3 解析main方法所在类

    通过当前堆栈信息,获取当前运行方法名为main的所在类. 解析main方法所在类主要目的就是为了输出日志信息使用,并不是为了解析启动类. 启动类是通过SpringApplication.run(…)方法的参数传递. 也就是说SpringBoot中启动类并不要求就是main()方法所在类.

    1.1.4 SpringBoot中组件排序规则

    SpringBoot组件的排序大多是使用
    org.springframework.core.annotation.AnnotationAwareOrderComparator实现.主要分为如下几种情况;

    1. 实现PriorityOrdered接口的组件单独排序比较,数值越小优先级越高
    2. 未实现PriorityOrdered接口的组件,会按照Ordered,@Order,@ javax.annotation.Priority顺序查找排序值进行排序,数值越小优先级越高
    3. 如果一个实现PriorityOrdered接口,一个实现Ordered接口,那么无论数值大小,始终是实现PriorityOrdered接口的组件优先级最高.

    1.2 springApplication.run(String… arg)方法执行

    SpringBoot启动的整个流程主要是在该方法中完成.主要包含:

    1. ConfigurableEnvironment实现类类型的推断与创建,不同类型配置属性的添加,例如: 程序参数, 系统环境变量, application.properties中的配置属性都将分别做为PropertySource保存在ConfigurableEnvironment中.
    2. ConfigurableApplicationContext的类型推断与创建,和其一些基本属性的添加操作,例如向上下文中添加Environment实例,添加数据类型转换其等.
    3. 控制台SpringBoot logo的打印
    4. SpringBoot启动流程不同阶段的事件发布等.

    1.2.1 StopWatch start 开启应用启动计时器

    StopWatch该类主要用于统计SpringBoot在整个启动过程中所耗费时间

    1.2.2 配置java.awt.headless模式

    该属性值默认被设置为true, 用于在缺失显示屏、鼠标或者键盘时的系统配置。对于后端服务来讲,很多都是需要将这个属性设置为true的。

    1.2.3 创建SpringApplicationRunListeners

    通过SpringFactoriesLoaderspring.factories中加载org.springframework.boot.SpringApplicationRunListener实现类并封装在SpringApplicationRunListeners对象的成员变量listeners集合中,默认实现只有一个org.springframework.boot.context.event.EventPublishingRunListener,主要用于在SpringBoot启动过程发布不同阶段产生的事件,这是一个典型的监听者模式,SpringApplicationRunListener接口中定义的方法即对应着不同的事件类型。如下:
    starting() 对应 ApplicationStartingEvent
    environmentPrepared(environment) 对应 ApplicationEnvironmentPreparedEvent
    contextPrepared(context) 对应 ApplicationContextInitializedEvent (SpringBoot2.1 中新增)
    contextLoaded(context) 对应 ApplicationPreparedEvent
    started(context) 对应 ApplicationStartedEvent
    running(context) 对应 ApplicationReadyEvent
    failed(context, throwable) 对应 ApplicationFailedEvent SpringBoot启动过程中出现异常都会发布该事件

    1.2.4 listeners.starting()发布ApplicationStartingEvent

    • LoggingApplicationListener 监听ApplicationStartingEvent事件,创建日志对象,但是未设置日志配置信息,此时日志不可用
    • BackgroundPreinitializer 监听ApplicationStartingEvent事件,创建线程异步执行一些类的静态初始化,例如DefaultFormattingConversionService中的sattic代码块

    1.2.5 创建ConfigurableEnvironment对象并添加属性值

    知识点: ConfigurableEnvironment继承Environment, Environment继承PropertyResolver,主要提供了对属性获取方法, AbstractEnvironment做为抽象类实现了ConfigurableEnvironment接口方法,其内部是通过List<PropertySource<?>>集合来保存不同类型的属性资源。
    例如: 通过System.getProperties()得到的系统属性就是一种类型的PropertySource,通过application.yml配置的属性是另一种属性资源. 当调用env.getProperty()获取属性值时,会遍历PropertySource集合,只要有一个PropertySource中有对应属性值则不再继续遍历查找,所以在集合中越靠前的属性优先级越高.
    在这里插入图片描述

    1. 根据应用类型推断创建ConfigurableEnvironment实例,非web环境使用StandardEnvironment,将应用程序参数封装到StandardEnvironment

    2. 发布ApplicationEnvironmentPreparedEvent事件,事件的发布是同步的,主要有两个重要的监听器监听该事件。

      1. ConfigFileApplicationListener实现了Order接口,设置的优先级最高,因此最先执行。
        通过读取spring.factoriesEnvironmentPostProcessor接口实现类,遍历调用接口方法,ConfigFileApplicationListener同时实现了接口EnvironmentPostProcessor,用于读取application.ymlapplication.properties等配置文件中的信息封装在Environment中。
        相关类:

            org.springframework.boot.env.EnvironmentPostProcessor
            org.springframework.boot.env.PropertySourceLoader
            org.springframework.boot.env.PropertiesPropertySourceLoader
            org.springframework.boot.env.YamlPropertySourceLoader
        

        配置中心接入的实现可以通过接口EnvironmentPostProcessorPropertySourceLoader实现

      2. DelegatingApplicationListener 从Environment中读取属性context.listener.classes指定的监听器,实例化之后排序,将其添加到成员变量事件广播器multicaster,并发布ApplicationEnvironmentPreparedEvent事件

    3. 调用ConfigurationPropertySources.attach(environment)将所有的PropertySource又包装成PropertySource放在environment。
      这里有个问题,是否会造成死循环 ? 不会,springBoot重写了Iterable.Iterable() 方法,看源码分析.
      但是SpringBoot使用attach方法导致的一个缺陷: 如果要获取的属性值不存在,则会造成多余的循环遍历. 看源码分析.

    4. environment中PropertySource的优先级如下:
      configurationProperties
      commandLineArgs
      systemProperties
      systemEnvironment
      random
      applicationConfig: [classpath:/application-dev.properties]
      applicationConfig: [classpath:/application.properties]

    1.2.6 创建Banner,打印SpringBoot logo

    源码见SpringApplication printBanner(environment)

    1.2.7 创建ConfigurableApplicationContext

    根据应用类型推断,创建相应的ConfigurableApplicationContext实现类对象,非web应用使用AnnotationConfigApplicationContext,通过反射创建其实例对象,而其构造函数中做了重要的工作.。即创建AnnotatedBeanDefinitionReader 对象,而AnnotatedBeanDefinitionReader在构造方法中通过AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);注册一系列后置处理器:

    1. 添加组件排序比较器,AnnotationAwareOrderComparator.INSTANCE
    2. 添加ContextAnnotationAutowireCandidateResolver处理@Lazy@Qualifier
    3. 注入ConfigurationClassPostProcessor BeanDefinition
      该类实现BeanDefinitionRegistryPostProcessor接口有两个非常重要的作用,
      • postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法中对classpath下类文件扫描
      • postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法中解析@Configuration注解和@Bean方法,对@Configuration进行cglib增强,防止同类中调用this方法创建多个不同的对象. 不能增强BeanDefinitionRegistryPostProcessor实现类.
    4. 注入AutowiredAnnotationBeanPostProcessor BeanDefinition, 用于针对 @value@Autowired标记的字段赋值等.
    5. 注入CommonAnnotationBeanPostProcessor BeanDefinition,用于处理@PostConstruct@PreDestroy注解
    6. 注入EventListenerMethodProcessor BeanDefinition其通过实现SmartInitializingSingleton接口,实现对方法@EventListener方法的收集,
    7. 注入DefaultEventListenerFactory BeanDefinition,使用适配器模式,将@EventListener标记的方法转为监听器

    1.2.8 从spring.factories加载SpringBootExceptionReporter

    从spring.factories中加载SpringBootExceptionReporter接口实现类,主要用在SpringBoot启动过程回调异常信息给开发者处理.

    1.2.9 prepareContext为ApplicationContext执行refresh做准备

    1. environment添加到ConfigurableApplicationContext
    2. ConfigurableBeanFactory添加数据类型转换器ApplicationConversionService
    3. 回调ApplicationContextInitializer接口方法,传入ConfigurableApplicationContext参数
    4. 发布ApplicationContextInitializedEvent事件
    5. 通过beanFactory.registerSingleton(…)applicationArguments添加到Spirng容器
    6. 将启动类注册为Spring BeanDefinition
    7. 发布ApplicationPreparedEvent事件,在EventPublishingRunListener发布事件之前会遍历所有的事件监听器,如果有监听器实现了ApplicationContextAware接口,则回调接口方法.并将SpringBootspring.factories中加载的监听器添加到ConfigurableApplicationContext中,之后的事件发布则是通过applicationContext中的事件广播器发布.

    1.2.10 refreshContext(context) 开始spring容器的生命周期

    该过程主要工作:

    1. 设置beanFactory的类加载器, SpringEL表达解析器, Aware接口的后置处理器,
    2. 重点是执行BeanFactoryPostProcessors,中文翻译后置处理器,详情见Spring容器的生命周期
    3. 注册BeanPostProcessors,BeanPostProcessor的使用见Spring中Bean的生命周期
    4. 注册事件广播器,SimpleApplicationEventMulticaster
    5. 添加事件监听器到广播器, 解析实现ApplicationListener接口的Bean名称保存在广播器
    6. 通过getBean()完成所有非懒加载的bean的初始化,详情见Spring中Bean的生命周期

    1.2.11 stopWatch.stop() 停止应用启动计时

    控制台打印应用启动时间

    1.2.12 listeners发布ApplicationStartedEvent事件

    发布该事件时整个应用服务基本可用,但是优先级高于ApplicationRunner和CommandLineRunner

    1.2.13 callRunners调用Runner回调接口方法

    org.springframework.boot.ApplicationRunner
    org.springframework.boot.CommandLineRunner
    这两个Runner没有继承关系,但是作用相同,都能够在应用启动后执行回调,并且可以得到应用启动时传入的参数,两者唯一区别就是方法参数类型不同

    1.2.14 listeners发布ApplicationReadyEvent事件

    自此整个SpringBoot应用启动完成

    展开全文
  • springboot启动流程

    2020-04-27 17:22:20
    springboot启动流程; 总体来说,分为两个核心步骤 1,创建SpringApplication对象 2,SpringApplication的run方法实现启动同时返回当前容器的上下文对象 分析一下详细的流程; 1,创建SpringApplication对象...

    springboot的启动流程;

    总体来说,分为两个核心步骤

    1,创建SpringApplication对象

    2,SpringApplication的run方法实现启动同时返回当前容器的上下文对象

    分析一下详细的流程;

    1,创建SpringApplication对象,指定springboot容器初始化操作

     

    构造函数内容:

    2,获取当前应用启动类型

        原理:判断当前classpath是否有加载我们的servlet类,返回servlet web的启动方式

        webApplicationType分为三种类型:

            1,REACTIVE 响应式启动(spring5新特性)

            2,NONE 不会嵌入web容器启动 (在将springboot项目放入外部服务器运行的时候使用,可以在application.yml中配置)

            3,SERVLET 基于web容器启动 (嵌入式web容器,由java语言创建)

    3,setlnitializers读取Spr ingBoot包下面的META- |NF/spring. factories获取到对应Appl icat ionContext Initializer装配到集合中,一共是6个

    4,setListeners 读取SpringBoot包下面的META- INF/spring.factories获取到对应ApplicationListener装配到集合中


    5,mainApplicationClass获取当前运行的主函数

    6,调用SpringApplication的run方法实现启动

     

    run方法内容:

    7,StopWatch stopWatch = new StopWatch();

    stopWatch.start();

       .....

    stopWatch.stop();

    记录springboot项目启动时间

    8,getRunListeners(args)读取所有包里面的META-INF/spring.factories文件中的SpringApplicationRunListener类型存入到集合中

    9,listeners.starting();循环执行集合中所有项的starting方法

    10,ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

    读取配置文件到springboot容器中

    11,Banner printedBanner = printBanner(environment);

    打印Banner图

    12,context = createApplicationContext();

    点击进入这个方法可以看到是判断webApplicationType类型

    servlet类型,创建AnnotationConfigServletWebServerApplicationContext对象

    13,refreshContext(context);  刷新上下文

    14,开始创建tomcat容器

    15,开始加载SpringMVC

    16,afterRefresh(context, applicationArguments);

    一个空的模板方法,可以供子类重写

    17,listeners.started(context);

    使用广播和回调机制通知监听器springboot容器已经启动成功

    18,listeners.running(context);

    使用广播和回调机制通知监听器springboot容器已经启动成功,可以正常运行项目

    19,最后返回当前上下文对象

     

    展开全文
  • SpringBoot启动流程简述

    2020-08-31 14:39:35
    又回顾了springboot启动流量,有了新的理解,进行以下补充: 1、listeners.starting()等方法,第一次出现了误解,以为是启动监听器,但是我很奇怪监听器为什么要启动。再次看源码,才知道不同的方法是用来发布不同的...

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    • 再次回顾了springboot启动流程,有了新的理解,进行以下补充:
    1. listeners.starting()等方法,第一次出现了误解,以为是启动监听器,但是我很奇怪监听器为什么要启动。再次看源码,才知道不同的方法是用来发布不同的事件,此方法就是发布ApplicationStartingEvent事件。可见看源码还是要耐心。
    • 启动流程二次总结
    1. 自定义启动类,main方法调用:SpringApplication.run(启动类.class,args);
    2. 调用SpringApplication构造方法实例化SpringApplication,实例化过程中做以下几件事:
      • 根据依赖判断webApplicationType,spring-web就是Servlet类型,spring-webflux就是Reactive类型
      • spring.factories文件读取ApplicationContextInitializer.class的所有配置实例实例化,放到全局变量;
      • spring.factories文件读取ApplicationListener.class的所有配置实例实例化,放到全局变量;
      • 推断主类class类型。
    3. 调用run()方法,所有的初始化工作在run()方法内完成,找重要的步骤说;
    4. 准备异常报告器空列表,用于后续报告异常,不重要;
    5. 设置jvm参数,无头服务(不太懂),不重要;
    6. 构建SpringApplicationRunListeners,spring.factories文件获取EventPublishingRunListener,通过此类对象调用2中的所有监听器,发布不同的事件,这一步首先发布ApplicationStartingEvent事件;
    7. 解析启动参数args,构建环境变量ConfigurableEnvironment,发布ApplicationEnvironmentPreparedEvent事件;
    8. 准备并打印Banner,printBanner(environment);
    9. 创建上下文,Servlet:AnnotationConfigServletWebServerApplicationContext,Reactive:AnnotationConfigReactiveWebServerApplicationContext
    10. 加载异常报告器;
    11. 准备上下文,其中做以下几件事:
      • 设置环境变量;
      • 初始化,调用2中的所有初始化器,发布ApplicationContextInitializedEvent事件;
      • 加载上下文,构建各种BeanDefinition,为后续Bean的加载、扫描做准备,同时发布ApplicationPreparedEvent事件;
    12. 刷新上下文,这是spring bean管理的核心步骤,其中解决循环依赖、启动Tomcat等服务器都是在此步骤实现,目前简要说明,会在Bean生命周期文章重点说明Bean的实例化过程。主要的工作如下:
      • 对相关属性、环境变量进行校验;
      • 准备BeanFactory,填充一些属性,注册相关单例对象(没有深入研究);
      • 没有找到是在哪一步进行注解、配置扫描这些
      • onRefresh()方法会启动webServer,如Tomcat;
      • finishBeanFactoryInitialization()创建单例,Bean的实例化、解决循环依赖均发生在此方法;
      • 完成刷新上下文,发布ContextRefreshedEvent事件;
    13. 发布ApplicationStartedEvent事件;
    14. 回调ApplicationRunner、CommandLineRunner等runner;
    15. 发布ApplicationReadyEvent事件;
    展开全文
  • SpringBoot启动过程

    万次阅读 多人点赞 2019-03-14 17:18:40
    SpringBoot启动过程分析,首先打开SpringBoot的启用入口Main类: @SpringBootApplication public class ApplicationMain{ public static void main(String[] args) { SpringApplication.run(ApplicationMain.class...
  • SpringBoot启动流程总结

    万次阅读 多人点赞 2019-06-30 21:06:45
    一直很好奇SpringBoot这么一个大怪物,启动的时候做了哪些事情,然后看了很多老师讲的教学视频,然后自己想好好整理一下,做下学习笔记下次也方便自己阅读 1、首先从main方法开始看 public static void main...
  • SpringBoot启动流程

    2021-01-08 14:26:52
    SpringBoot启动流程
  • springBoot启动流程

    2020-07-10 15:09:23
    springboot启动的时候会先去调用WebApplicationType.deduceFromClasspath();推断项目类型,假如是一个web项目的话会给属性webApplicationType赋值SERVLET,然后在去创建context = createApplicationContext();时...
  • Springboot启动流程

    2020-09-23 18:18:49
    转载自springboot启动流程图 详细讲解:讲解
  • 面试题题目:SpringBoot启动流程 1. 基本工程环境 1.1 一个简单的Maven工程 1.2 基本pom(只需要web即可) 1.3一个简单的启动类 2.源码大致解析 2.1 主方法(main) 1.创建一个Spring应用 new ...
  • SpringBoot2 | SpringBoot启动流程源码分析(一)

    万次阅读 多人点赞 2018-08-31 15:29:58
    概述: 前阵子看到了SpringCloud社区的一个...另外在现有的springboot专栏中,大多数博文旨在应用,对一些中间件的整合之类,源码分析的博客数量有限。鉴于以上两方面,该系列应运而生。 该系列主要还是Spri...
  • 面试经常会问道springboot启动流程或者原理,看了多数博友的文章,都是大同小异,但是面试的时候不可能那么多,所以我将启动流程总结一下。 启动流程: 1.启动springboot这需要执行SpringApplication执行类即可 ...
  • 简述SpringBoot启动流程

    2020-04-23 22:26:41
    转载于:SpringBoot启动流程总结 先写个总结: 1、new了一个SpringApplication对象,使用SPI技术加载spring.factories文件中ApplicationContextInitializer、ApplicationListener 接口实例 2、调用SpringApplication...
  • SpringBoot启动流程解析

    万次阅读 多人点赞 2018-07-28 22:31:51
    写在前面:  由于该系统是底层系统,以微服务形式对外暴露dubbo服务,所以本流程中SpringBoot不基于jetty或者tomcat等容器启动方式发布服务... 本文以调试一个实际的SpringBoot启动程序为例,参考流程中主要类类...
  • 高级面试题--SpringBoot启动流程解析

    万次阅读 多人点赞 2019-09-03 09:13:32
    写在前面: 由于该系统是底层系统,以微服务形式对外暴露dubbo服务,所以本流程中SpringBoot不基于jetty或者tomcat等容器启动方式发布服务,而是以执行程序方式启动...上图为SpringBoot启动结构图,我们发现启动流程...
  • main里面调用SpringApplication.run()启动整个Spring Boot程序,该方法所在类需要使用@SpringBootApplication注解。 @SpringBootApplication包括三个注解: @EnableAutoConfiguration:SpringBoot根据应用所声明...
  • 这就是Spring Boot的整个启动流程,其核⼼就是在Spring容器初始化并启动的基础上加⼊各种扩展点,这些扩展点包括: ApplicationContextInitializer、ApplicationListener以及各种BeanFactoryPostProcessor等等。你对...
  • springboot启动流程及原理

    千次阅读 2019-12-26 23:36:51
    springboot启动入口类 @SpringBootApplication public class SpringBootWebApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(SpringBootWebA...
  • SpringBoot启动过程原理一

    万次阅读 多人点赞 2018-06-06 12:20:35
    1.1 Springboot启动: @SpringBootApplication public class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class,args); } } 从上面代码看,调用了...
  • 一、springboot运行流程 1、springboot获取配置的流程 上图是我对springboot获取配置流程的简单总结。 运行主程序时,调用了@SpringBootApplication注解,这个注解又包含一个@Import注解,用于导入配置类。 这个@...
  • SpringBoot启动流程原理

    2020-03-04 00:42:54
    spring boot的启动流程 一、初始化SpringAppliaction对象 1. 设置应用的容器类型 当前的web应用类型(webApplicationType)是在SpringApplication的构造函数中设置的,设置的逻辑在WebApplicationType....
  • SpringBoot启动流程简析(一)

    万次阅读 2017-12-13 21:11:31
    我想很多人已经在项目中使用SpringBoot做项目开发的工作了,创建SpringBoot和启动SpringBoot应用都会较简单一点,下面我以SpringBoot官网上的Demo来简单的分析一些SpringBoot启动流程,我们的启动主类代码如下:@...
  • 前言 前一篇分析了SpringBoot如何启动以及内置web容器,这篇我们一起看一下SpringBoot的整个启动过程,废话不多说,正文开始。 正文
  • SpringBoot2 | SpringBoot启动流程源码分析(二)

    万次阅读 多人点赞 2018-09-03 16:01:43
    在上一篇SpringBoot | SpringBoot2 | SpringBoot2启动流程源码分析(一)中我们提到springBoot启动流程大致有以下7点: 第一步:获取并启动监听器 第二步:构造容器环境 第三步:创建容器 第四步:实例化...
  • SpringBoot启动流程解析(总结的非常好,很清晰!)

    万次阅读 多人点赞 2019-03-25 11:44:00
    由于该系统是底层系统,以微服务形式对外暴露dubbo服务,所以本流程中... 本文以调试一个实际的SpringBoot启动程序为例,参考流程中主要类类图,来分析其启动逻辑和自动化配置原理。 总览: 上图为Sprin...
  • springboot启动原理, 源码发现,过程详解 SpringBootApplication背后的秘密 深入探索SpringApplication执行流程
  • SPRINGBOOT启动流程及其原理 Spring Boot、Spring MVC 和 Spring 有什么区别? 一 springboot启动原理及相关流程概览 二 springboot的启动类入口 三 单单是SpringBootApplication接口用到了这些注解  1)@...
  • SpringBoot 启动流程

    2020-12-01 14:08:57
    1、编写一个SpringBoot启动类 运行一个SpringBoot项目,引入相关Starters和相关依赖后,再编写一个启动类,然后在这个启动类标上@SpringBootApplication注解,然后就可以启动运行项目了,我们在MyApplication启动类...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 79,549
精华内容 31,819
关键字:

springboot启动流程

spring 订阅