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

【SpringBoot】 SpringBoot启动流程浅分析

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

【SpringBoot】 SpringBoot启动流程浅分析

SpringBoot启动流程浅分析 一.启动类 1.@SpringBootApplication注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

关于自动配置的流程,可以去看这篇博文

【Spring Boot】Spring Boot 自动配置原理 图文并茂_秋日的晚霞的博客-CSDN博客

2.main方法
   public static void main(String[] args) {
        SpringApplication.run(AppTest.class, args);
    }

跟进去

首先看方法声明 静态方法 返回一个 ConfigurableApplicationContext 接口实现类对象

可以看到有非常多的实现类及子接口 那到底是怎么选择实现类对象的? 带着这个问题继续往下跟源码

primarySources   //主启动类的class对象  
args   //main方法的启动参数

在这new 了一个 SpringApplication 实例,调用了run方法

new SpringApplication()

跟进 new SpringApplication(primarySources) 方法

public SpringApplication(Class... primarySources) {
		this(null, primarySources);
	}

创建一个新的 SpringApplication 实例。应用程序上下文将从指定的主要来源加载 bean

继续跟进构造方法

resourceLoader  //资源加载器   此时为null 

this.resourceLoader = resourceLoader;
primarySources  //容器中bean的来源   此时为主启动类的字节码对象

这里断言 primarySources 不能为null 否则将抛出异常

Assert.notNull(primarySources, "PrimarySources must not be null");

方法形参上 primarySources 是一个可变参 接下来将primarySources 变成了一个 linkedHashSet

this.primarySources = new linkedHashSet<>(Arrays.asList(primarySources));

linkedHashSet set集合 元素不重复 底层是链表 保证了存储有序

然后执行了 这么一行代码

this.webApplicationType = WebApplicationType.deduceFromClasspath();

这个 webApplicationType 是什么呢 点进去可以看到是一个枚举 有三个枚举项

	
	NONE,

	
	SERVLET,

	
	REACTIVE;

判断当前项目类型 这里返回 WebApplicationType.SERVLET 也就是当前 SpringApplication 的类型为 Web 应用程序,内置servlet Web 服务器

接下来设置了监听器

setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

然后设置程序入口

this.mainApplicationClass = deduceMainApplicationClass()

SpringApplication.run()

接下来看run方法做了什么

StopWatch stopWatch = new StopWatch();   //计时器
stopWatch.start();  //开始计时

设置了一个名为java.awt.headless的系统属性

configureHeadlessProperty()

获取Spring应用上下文引导类的监听器,

SpringApplicationRunListeners listeners = getRunListeners(args)

跟进去发现,发布了ApplicationStartingEvent事件

listeners.starting();

封装参数SpringApplication引导类需要的参数

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)

准备环境

ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

根据当前环境忽略不需要的bean

configureIgnoreBeanInfo(environment);

打印 Banner

Banner printedBanner = printBanner(environment)

创建ApplicationContext上下文 之前看到 webApplicationType 的类型是 SERVLET

context = createApplicationContext()

返回AnnotationConfigServletWebServerApplicationContext字节码对象 然后调用 BeanUtils.instantiateClass 实例化

class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
		implements AnnotationConfigRegistry 

继承自 ServletWebServerApplicationContext

刷新上下文 最终复用了Spring的刷新容器方法

refreshContext(context);

调用 ConfigurableApplicationContext .refresh()方法

再调用org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh

最后调用 org.springframework.context.support.AbstractApplicationContext#refresh

刷新容器的12个方法可以去看这篇博文

【Spring】SpringIOC容器启动过程源码分析 以及 循环依赖问题_秋日的晚霞的博客-CSDN博客

最后就是停止计时以及打印日志

        stopWatch.stop();

        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }


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

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

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