把spring应用跑起来
开始进入run方法:
public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
step into run()
public ConfigurableApplicationContext run(String... args) {
//停止监听器,监控整个应用的启动和停止的
StopWatch stopWatch = new StopWatch();
//start方法里的源码可以看下面代码展示
stopWatch.start();
//记录应用的启动时间
//创建引导上下文(xxxContext都是引导环境)
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
//createBootstrapContext方法的源码在下面
ConfigurableApplicationContext context = null;
//让当前应用进入headless模式。源码在下面
//(headless是自力更生的意思,不依赖别人)
configureHeadlessProperty();
//获取所有RunListener(运行监听器)保存到SpringApplicationRunListeners
//【为了方便所有Listener进行事件感知】所谓的监听器就是监听到当前项目的状态
SpringApplicationRunListeners listeners = getRunListeners(args);
//starting()源码分析在下面
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//准备ApplicationArguments应用参数,应用参数是从命令行里传过来的。即保存命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备运行时环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
//这行代码结束后,所有的环境信息已经准备就绪
//配置一些要忽略的bean信息
configureIgnoreBeanInfo(environment);
//打印banner(banner是啥,可以看下面)
Banner printedBanner = printBanner(environment);
//创建ioc容器(容器创建完成后,所有的bean都会进去)
context = createApplicationContext();
//源码在下面
//把Startup信息保存起来
context.setApplicationStartup(this.applicationStartup);
//准备ioc容器环境的信息(源码在下面)
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;
}
【8.1、SpringBoot启动流程--把spring应用跑起来】
文章图片
banner:
._______ _ _
/\\ / ___'_ __ _ _(_)_ ____ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/___)| |_)| | | | | || (_| |) ) ) )
'|____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::(v2.4.0)
start方法里的源码
public void start() throws IllegalStateException {
this.start("");
}public void start(String taskName) throws IllegalStateException {
if (this.currentTaskName != null) {
throw new IllegalStateException("Can't start StopWatch: it's already running");
} else {
//给stopWatch对象保存一些信息
this.currentTaskName = taskName;
//当前任务的名字
this.startTimeNanos = System.nanoTime();
//当前的时间
}
createBootstrapContext创建引导上下文
private DefaultBootstrapContext createBootstrapContext() {
//创建默认的引导上下文对象
//以后就会给里面保存很多信息
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
//遍历所有之前的获取到的bootstrappers,调用每一个bootstrappers的intitialize() 来完成对引导启动器上下文环境设置
this.bootstrappers.forEach((initializer) -> initializer.intitialize(bootstrapContext));
return bootstrapContext;
//null
}
=============================================================
public interface Bootstrapper {/**
* Initialize the given {@link BootstrapRegistry} with any required registrations.
* @param registry the registry to initialize
*/
//传入引导注册工厂
//这个工厂里面可以给他加入一些当前上下文的一些引导环境信息
void intitialize(BootstrapRegistry registry);
}
让当前应用进入headless模式
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
获取所有RunListener(运行监听器)
所谓的监听器就是监听到当前项目的状态
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class>[] types = new Class>[] { SpringApplication.class, String[].class };
//new SpringApplicationRunListeners:相当于把找到的Listener保存到SpringApplicationRunListener;
return new SpringApplicationRunListeners(logger,
//getSpringFactoriesInstances: 去spring.factories找SpringApplicationRunListener
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}=====================================================
SpringApplicationRunListeners(Log log, Collection extends SpringApplicationRunListener> listeners,
ApplicationStartup applicationStartup) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
this.applicationStartup = applicationStartup;
}List listeners;
文章图片
starting():
遍历所有的
SpringApplicationRunListener
调用 starting
方法;相当于通知所有感兴趣系统正在启动过程的人,项目正在 starting。(即告诉我这个项目正在启动)void starting(ConfigurableBootstrapContext bootstrapContext, Class> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}=========================================
进入doWithListeners方法:
private void doWithListeners(String stepName, Consumer listenerAction,
Consumer stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
//遍历所有的listeners,现在进行到哪一步了,相当于一个事件信息
this.listeners.forEach(listenerAction);
if (stepAction != null) {
stepAction.accept(step);
}
step.end();
}================================
进入this.listeners.forEach(listenerAction):
void starting(ConfigurableBootstrapContext bootstrapContext, Class> mainApplicationClass) {
//遍历所有的SpringApplicationRunListener调用starting方法
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
准备环境 :
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
//如果当前有上下文环境信息,就获取并返回;没有就创建
//比如保存底层运行的环境变量
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置环境(拿到环境信息,命令行参数)
configureEnvironment(environment, applicationArguments.getSourceArgs());
//绑定环境信息
ConfigurationPropertySources.attach(environment);
//监听器调用 listener.environmentPrepared();通知所有的监听器当前环境准备完成
listeners.environmentPrepared(bootstrapContext, environment);
//将环境信息设置到类的最后(这个不用管)
DefaultPropertiesPropertySource.moveToEnd(environment);
//配置额外的Profiles,激活哪些环境(不用管)
configureAdditionalProfiles(environment);
//绑定工作(都是找到一些东西,把一些属性绑定到某个值里面)
bindToSpringApplication(environment);
//又是准备一些环境信息
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
//准备完了后,把环境信息再次绑定
ConfigurationPropertySources.attach(environment);
return environment;
}
推荐阅读
- java|零基础微信完整版小程序开发之微信表情包小程序前端+后台源码(java)
- springboot|Spring Security跨站请求伪造(CSRF)
- flowable|spring cloud alibaba gateway nacos 503错误代码
- SpringBoot+Uniapp实战开发全新仿抖音短视频App某课内置资料
- java|springboot 整合redis集群
- SpringBoot|SpringBoot 根据 注解和切面(AOP) 实时验证用户登陆状态
- springBoot|自定义拦截器实现权限校验
- springBoot|springBoot使用拦截器实现权限验证,解决注入为空
- springboot|Springboot+Shiro+Vue博客管理系统