当前位置 : 主页 > 编程语言 > java >

springboot 启动流程

来源:互联网 收集:自由互联 发布时间:2022-10-26
springboot 启动源码解析 注: 以下源码是基于: 2.2.6.RELEASE 版本做的摘录分析 parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starters/artifactId version2.2.6.RELEASE/version /parent dependencies depe


springboot 启动源码解析

注: 以下源码是基于: 2.2.6.RELEASE 版本做的摘录分析

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

大致类图:

springboot 启动流程_监听器

@SpringBootApplication
public class CollmallProductApplication {

public static void main(String[] args) {
SpringApplication.run(CollmallProductApplication.class, args);
}
}public class SpringApplication {

private boolean logStartupInfo;
private boolean headless;
private Banner banner;
private ResourceLoader resourceLoader;

// 构造器 1
public SpringApplication(Class... primarySources) {
this((ResourceLoader)null, primarySources);
}
// 构造器 2
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}

// 此处省略很多行代码

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}

public ConfigurableApplicationContext run(String... args) {
// 1. 创建并启动计时监控类:此计时器是为了监控并记录 Spring Boot 应用启动的时间的,它会记录当前任务的名称,然后开启计时器。
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 2. 声明应用上下文和异常报告集合: 此过程声明了应用上下文对象和一个异常报告的 ArrayList 集合。
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
// 3. 设置系统属性 headless的值:设置 Java.awt.headless = true,其中 awt(Abstract Window Toolkit)的含义是抽象窗口工具集。设置为 true 表示运行一个 headless 服务器,可以用它来作一些简单的图像处理。
this.configureHeadlessProperty();
// 4. 创建所有 Spring 运行监听器并发布应用启动事件:此过程用于获取配置的监听器名称并实例化所有的类。
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();

Collection exceptionReporters;
try {
// 5. 处理args 参数:也就是说声明并创建一个应用参数对象。
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 6. 配置环境: 创建配置并且绑定环境(通过 property sources 和 profiles 等配置文件)。
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
// 7. 创建Banner 的打印类: 此 banner 信息是在 SpringBootBanner 类中定义的,可以通过实现 Banner 接口来自定义 banner 信息,然后通过代码 setBanner() 方法设置 Spring Boot 项目使用自己自定义 Banner 信息,或者是在 resources 下添加一个 banner.txt,把 banner 信息添加到此文件中,就可以实现自定义 banner 的功能了。
Banner printedBanner = this.printBanner(environment);
// 8. 创建应用上下文:根据不同的应用类型来创建不同的 ApplicationContext 上下文对象。
context = this.createApplicationContext();
// 9. 实例化异常报告器:它调用的是 getSpringFactoriesInstances() 方法来获取配置异常类的名称,并实例化所有的异常处理类。
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
// 10. 准备应用上下文:此方法的主要作用是把上面已经创建好的对象,传递给 prepareContext 来准备上下文,例如将环境变量 environment 对象绑定到上下文中、配置 bean 生成器以及资源加载器、记录启动日志等操作。
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 11. 刷新应用上下文:此方法用于解析配置文件,加载 bean 对象,并且启动内置的 web 容器等操作。
this.refreshContext(context);
// 12. 应用上下文刷新之后的事件处理:这个方法的源码是空的,可以做一些自定义的后置处理操作。
this.afterRefresh(context, applicationArguments);
// 13. 停止计时监控类:停止此过程第一步中的程序计时器,并统计任务的执行信息。
stopWatch.stop();
// 14. 输入日志记录执行主类名, 时间信息 :把相关的记录信息,如类名、时间等信息进行控制台输出。
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
// 15. 发布应用上下文启动完成事件:触发所有 SpringApplicationRunListener 监听器的 started 事件方法。
listeners.started(context);
// 16. 执行所有Runner 运行器:执行所有的 ApplicationRunner 和 CommandLineRunner 运行器。
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}

try {
// 17. 发布应用上下文就绪事件:触发所有的 SpringApplicationRunListener 监听器的 running 事件。
listeners.running(context);
// 18 .返回上下文对象
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}

// ===============================================================================================
// 以下是主要方法的实现
private void configureHeadlessProperty() {
System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
}

private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}

private Banner printBanner(ConfigurableEnvironment environment) {
if (this.bannerMode == Mode.OFF) {
return null;
} else {
ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader(this.getClassLoader());
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter((ResourceLoader)resourceLoader, this.banner);
return this.bannerMode == Mode.LOG ? bannerPrinter.print(environment, this.mainApplicationClass, logger) : bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
}

protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch(this.webApplicationType) {
case SERVLET:
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
}
} catch (ClassNotFoundException var3) {
throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
}
}

return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
// 获取springFactories的实例
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = this.getClassLoader();
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

public ClassLoader getClassLoader() {
return this.resourceLoader != null ? this.resourceLoader.getClassLoader() : ClassUtils.getDefaultClassLoader();
}

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
this.applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}

ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}

if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}

if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}

Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
this.load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}

private void refreshContext(ConfigurableApplicationContext context) {
this.refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
} catch (AccessControlException var3) {
;
}
}
}

protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
}

void started(ConfigurableApplicationContext context) {
Iterator var2 = this.listeners.iterator();
while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
listener.started(context);
}

}

private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
Iterator var4 = (new LinkedHashSet(runners)).iterator();

while(var4.hasNext()) {
Object runner = var4.next();
if (runner instanceof ApplicationRunner) {
this.callRunner((ApplicationRunner)runner, args);
}

if (runner instanceof CommandLineRunner) {
this.callRunner((CommandLineRunner)runner, args);
}
}
}

void running(ConfigurableApplicationContext context) {
Iterator var2 = this.listeners.iterator();

while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
listener.running(context);
}
}
}@FunctionalInterface
public interface Banner {
void printBanner(Environment environment, Class<?> sourceClass, PrintStream out);

public static enum Mode {
OFF,
CONSOLE,
LOG;

private Mode() {
}
}
}

到此为止 Spring Boot 的启动程序就结束了。


【文章转自印度服务器 http://www.558idc.com/yd.html提供,感恩】
上一篇:nginx 基于 certbot 构建https
下一篇:没有了
网友评论