SpringBoot源码分析系列之二:启动原理分析

引言
我们都知道SpringBoot是目前微服务比较流行的技术选型,它可以将工程打成war包的方式在tomcat进行启动,也可以打成jar包,直接对外提供服务。那我们就会好奇,它是怎么去启动服务的,同时是怎么去加载前端页面、js文件、配置文件以及class文件等等然后向外提供web服务的。带着一系列的疑问,一步步探究SpringBoot的启动原理。

  • SpringBoot大致启动流程

  • 源码跟踪分析

  • 总结


1.SpringBoot大致启动流程如下图所示。

这里写图片描述

2.源码跟踪分析

(1)main函数为主程序入口,SpringApplication调用run方法来启动SpringBoot服务。注解的含义在上一篇文章中进行了说明,这里不再赘述。

@SpringBootApplication(scanBasePackages = {"com.hikvision.center"})
@MapperScan("com.hikvision.center.module.mapper")
@ImportResource(locations = {"classpath:springMVC-servlet.xml"})
@ServletComponentScan
public class WebApplication extends SpringBootServletInitializer{
	static Logger logger = LoggerFactory.getLogger(WebApplication.class);
	public static void main(String[] args) {
	        //程序入口
			SpringApplication.run(WebApplication.class, args);
		
	}


}

(2)run方法是一个静态方法,主要执行一系列的初始化加载操作。

 //
public static ConfigurableApplicationContext run(Object source, String... args) {
	return run(new Object[] { source }, args);
}

(3)ConfigurableApplicationContext表示该 Context 是可修改的,也就是在构建 Context中用户可以动态添加或修改已有的配置信息。下图为ApplicationContext类关系图。
这里写图片描述

//创建了SpringApplication实例,同时调用run方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
	return new SpringApplication(sources).run(args);
}

(4)初始化操作。

//SpringApplication构造函数中,进行初始化操作,上下文从指定的源中加载bean,实例可以在被调用前进行自定义
public SpringApplication(Object... sources) {
		initialize(sources);
	}

(5)主要是为SpringApplication对象赋一些初值。

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
	if (sources != null && sources.length > 0) {
		this.sources.addAll(Arrays.asList(sources));
	}
	//判断当前允许的环境是否为web环境
	this.webEnvironment = deduceWebEnvironment();
	//
	setInitializers((Collection) getSpringFactoriesInstances(
			ApplicationContextInitializer.class));
	//
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	//
	this.mainApplicationClass = deduceMainApplicationClass();
}

(6)回到run方法中去看具体的实现,该方法主要完成ApplicationContext配置加载。

public ConfigurableApplicationContext run(String... args) {
	//性能检查,查看代码的运行时间
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	//设置上下文ID,设置父应用上下文,添加监听器和刷新容器相关的操作等
	ConfigurableApplicationContext context = null;
	//异常分析器
	FailureAnalyzers analyzers = null;
	//设置java.awt.headless属性,
	configureHeadlessProperty();
	//创建应用监听器SpringApplicationRunListeners同时开始监听
	SpringApplicationRunListeners listeners = getRunListeners(args);
	//启动监听器
	listeners.started();
	try {
		//获取启动参数
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(
				args);
		//加下SpringBoot配置环境
		ConfigurableEnvironment environment = prepareEnvironment(listeners,
				applicationArguments);
		//定义输出的标志,打印spring
		Banner printedBanner = printBanner(environment);
		//创建应用上下文
		context = createApplicationContext();
		//注册异常分析器
		analyzers = new FailureAnalyzers(context);
		//为ApplicationContext加载environment,初始化IoC容器,调用SpringApplicationRunListener的contextLoaded()方法,完成IOC容器加载
		prepareContext(context, environment, listeners, applicationArguments,
				printedBanner);
		//初始化自动配置
		refreshContext(context);
		//SpringBoot完成ApplicationContext初始化
		afterRefresh(context, applicationArguments);
		//广播已经完成初始化全部过程
		listeners.finished(context, null);
		//关闭任务执行还见监听器
		stopWatch.stop();
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass)
					.logStarted(getApplicationLog(), stopWatch);
		}
		return context;
	}
	catch (Throwable ex) {
		handleRunFailure(context, listeners, analyzers, ex);
		throw new IllegalStateException(ex);
	}
}

3.总结
从以上Springboot启动过程来看,它主要创建了程序配置环境(environment)、事件监听(listeners)、应用上下文(applicationContext),并在以上基础上,在容器中开始加载和实例化我们需要的Bean,在这些过程中有些过程是可以自定义的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕枫技术笔记

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值