一、启动配置原理
启动流程分析:
1.debug方式启动springboot
2.run springApplication
上面的run方法调用下面的重载run方法,参数从Class<?>primarySource
转换成 Class<?>[] primarySources,具体调用下面的重载方法返回一个ConfigurableApplicationContext对象
3.初始化一个SpringApplication容器,参数是primarySources
调用其有参构造方法
4.开始初始化参数
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//初始化一个set
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.resourceLoader = resourceLoader;
//非空声明
Assert.notNull(primarySources, "PrimarySources must not be null");
//将primarySources所有参数存入primarySources属性中
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
//查询有没有DispatcherHandler这样的组件,判断是否为web环境
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer保存起来
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//从类路径下找到META-INF/spring.factories配置的所有ApplicationListener保存起来
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//查询所有配有main的主方法类
this.mainApplicationClass = this.deduceMainApplicationClass();
}
这里以this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));为例分析
- 方法调用是将获得的Spring工厂实例化初始化加载器initializers加入到这个SpringApplication类的集合initializers
2. 那么这些initializers从何而来?那就是this.getSpringFactoriesInstances(ApplicationContextInitializer.class).查看getSpringFactoriesInstances方法的调用,就是进一步调用this.getSpringFactoriesInstances
3.那么来到getSpringFactoriesInstances方法,发现调用SpringFactoriesLoader类加载器去加载工厂
4.可以看到类加载器加载的是location是"META-INF/spring.factories"
5.加载的就是我们自动配置文件
6.其他的也同理不做赘述,进行自动配置初始化后,SpringApplication进行了初始化,并且放入集合中待激活
5.run方法运行
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
//获取之前已经初始化好的监听器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//开启监听器
listeners.starting();
Collection exceptionReporters;
try {
//封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境,准备完成监听器也会回调listeners.environmentPrepared((ConfigurableEnvironment)environment);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
//根据环境创建printedBanner
Banner printedBanner = this.printBanner(environment);
//创建容器,根据环境判断是普通容器还是web容器
context = this.createApplicationContext();
//加载SpringBootExceptionReporter异常上报实例,放入上下文环境中
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//准备上下文环境,最后回调listeners.contextLoaded(context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//ioc容器根据上下文环境,加载嵌入式服务器,配置,组件等等,控制台有输出
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
//回调spirngApplicationListener的Start方法
listeners.started(context);
//调用下叙两句
//runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
//runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
//从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
//ApplicationRunner先回调,CommandLineRunner再回调
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
//监听器run
listeners.running(context);
//整个springboot开始run,最后返回容器
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
启动源码分析大致就是这些,如有问题请您批评指正~