启动流程
- 创建SpringApplication
SpringApplication.run(DemoApplication.class, args);
这是主程序的入口,该代码会运行以下方法:
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
// 先创建SpringApplication来引导程序的运行,然后执行run()方法
return new SpringApplication(primarySources).run(args);
}
1.1
new SpringApplication(primarySources)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 判断是不是web应用,如果是web应用的话就SERVLET枚举:应用程序应该作为基于servlet的web应用程序运行,并且应该启动嵌入式servlet web服务器。
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 设置初始化器。也就是创建ApplicationContextInitializer接口的实现类的对象并获取过来存到this.initializers集合中
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置监听器。
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 决定哪个类是主程序入口类。运行SpringApplication时是可以传入多个类的
this.mainApplicationClass = deduceMainApplicationClass();
}
1.1.1
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
// 该方法调用下面的getSpringFactoriesInstances()方法
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取类加载器
ClassLoader classLoader = getClassLoader();
// 使用名称并确保唯一,防止重复。声明Set集合
// 从META-INF/spring.factories中获取ApplicationContextInitializer配置下的所有name
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 创建Spring工厂实例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 对ApplicationContextInitializer接口的实现对象进行排序
AnnotationAwareOrderComparator.sort(instances);
// 返回存储着ApplicationContextInitializer接口的实现对象的List
return instances;
}
1.1.1.1
createSpringFactoriesInstances(, parameterTypes, classLoader, args, names)
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
// 创建List集合并设置大小
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
// 通过反射创建每一个ApplicationContextInitializer接口实现类的对象
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = (T) BeanUtils.instantiateClass(constructor, args);
// 将创建出来的对象存进List集合中
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
1.1.2
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
// 该方法调用下面的getSpringFactoriesInstances()方法
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// 获取类加载器
// 使用名称并确保唯一,防止重复。声明Set集合
// 从META-INF/spring.factories中获取ApplicationListener配置下的所有name
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 创建Spring工厂实例。通过反射创建每一个ApplicationListener接口实现类的对象
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 对ApplicationListener接口的实现对象进行排序
AnnotationAwareOrderComparator.sort(instances);
// 返回存储着ApplicationListener接口的实现对象的List
return instances;
}
1.1.2
this.mainApplicationClass = deduceMainApplicationClass();
决定主程序入口类
private Class<?> deduceMainApplicationClass() {
try {
// 获取堆栈跟踪类
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
// 判断类是不是包含main方法,如果是,创建该类
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
- 执行run()方法:执行SpringBoot程序,创建并刷新IOC容器
public ConfigurableApplicationContext run(String... args) {
// 监听springboot启动对象
StopWatch stopWatch = new StopWatch();
// 开启计时器
stopWatch.start();
// 声明IOC容器
ConfigurableApplicationContext context = null;
// 声明错误报告集合
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 对headless对象进行配置(与awt应用有关)
configureHeadlessProperty();
// 获取SpringApplication.run()运行时的监听器。参考1.1.1的运行流程
SpringApplicationRunListeners listeners = getRunListeners(args);
// 调用所有的listener的starting()方法
listeners.starting();
try {
// 获取到命令行参数,封装成一个ApplicationArguments对象
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备配置环境。
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 配置忽略bean信息
configureIgnoreBeanInfo(environment);
// 打印Banner
Banner printedBanner = printBanner(environment);
// 创建IOC容器
context = createApplicationContext();
// 获取错误记录器,用来记录错误信息
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 配置IOC容器、打印Banner等
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
/*
刷新容器。
扫描、创建、加载所有组件,并对组件进行配置等操作都在这里。
*/
refreshContext(context);
// 里面没有代码,猜测是让我们来自定义里面的代码
afterRefresh(context, applicationArguments);
// 停止计时器
stopWatch.stop();
// 对日志的打印等操作
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 调用所有的 ApplicationListener 中的 started() 方法
listeners.started(context);
/*
ApplicationRunner
CommandLineRunner
在IOC容器中获取到
ApplicationRunner
CommandLineRunner
这两个类型的组件,然后存储到一个List集合中,判断他们是否是这两个类型的组件,如果是,则调用他们的 run() 方法。
*/
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 调用所有的 ApplicationListener 中的 running() 方法
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
// 返回IOC容器
return context;
}
2.1
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
准备环境
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 创建环境
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 配置环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
// 调用环境准备完成方法:调用所有的SpringApplicationRunListener中的environmentPrepared()方法
listeners.environmentPrepared(environment);
// 将环境environment绑定到SpringApplication应用(主程序入口类)中
bindToSpringApplication(environment);
// 判断是否是自定义的环境
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
2.1.1
ConfigurableEnvironment environment = getOrCreateEnvironment();
获取或者创建环境(Enviroment)
private ConfigurableEnvironment getOrCreateEnvironment() {
// 如果已有环境,则使用已有环境
if (this.environment != null) {
return this.environment;
}
// 根据当前web应用类型来获取对应的环境
switch (this.webApplicationType) {
// 在1.1可以看到怎么获取的webApplicationType
case SERVLET:
// 如果是web应用,那么会创建该环境
return new StandardServletEnvironment();
case REACTIVE:
// 如果不是web应用,那么会创建该环境
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
2.1.2
configureEnvironment(environment, applicationArguments.getSourceArgs());
配置环境
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
// 获取转换器实例
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
// 在环境中使用上面获取的转换器实例设置转换器服务
environment.setConversionService((ConfigurableConversionService) conversionService);
}
// 配置属性源:为springboot添加默认属性(如果有配置文件则不添加默认属性)和添加命令行属性(如果有的话)
configurePropertySources(environment, args);
// 配置profiles环境(如果有配置的话)
configureProfiles(environment, args);
}
2.2
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
准备上下文
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
// 将刚才创建的环境对象设置到IOC容器中
context.setEnvironment(environment);
postProcessApplicationContext(context);
/*
配置应用初始化器:
调用前面获取到的所有的 ApplicationContextInitializer 的 initialize() 方法
*/
applyInitializers(context);
// 调用前面获取到的所有的 ApplicationListener 的 contextPrepared() 方法
listeners.contextPrepared(context);
// 打印日志
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// 添加引导特定的单例beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 注册命令行单例到beanFactory中
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
// 将Banner注册到beanFactory中
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 = getAllSources();
// 断言
Assert.notEmpty(sources, "Sources must not be empty");
// 将主程序加载到IOC容器中
load(context, sources.toArray(new Object[0]));
// 调用前面创建的所有的 ApplicationListener 的 contextLoaded() 方法
listeners.contextLoaded(context);
}