SpringBoot启动流程
以下将从springboot的入口类SpringApplication.run(TestApplication.class,args);开始分析
1 进入run方法会先调用new SpringApplication()构造方法进行初始化操作
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//把primpriarySources(就是传过来的启动类)放入一个set
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//判断当前web类型(REACTIVE,NONE,SERVLET),这里返回SERVLET
this.webApplicationType = WebApplicationType.deduceFromClasspath();
/**
从两个spring.factories(分别是springboot和springboot-autoconfigure包里的
META-INF/spring.factories,jar包都是放入classpath目录中的,
classpath下有多少个spring.factories就读取多少个)中取出7个初始化器
(根据ApplicationContextInitializer作为key来取),
取出的只是类得完全限定名,然后进行实例化放到initializers中(是一个list)
*/
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
/**
从两个spring.factories中取出11个监听器器,取出的只是类得完全限定名,
然后进行实例化放到listeners中(是一个list)
*/
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
1.1 上一步中的getSpringFactoriesInstances方法
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
//这个方法执行的核心方法是SpringFactoriesLoader.loadFactoryNames
//其实就是解析spring.factories,从中取出类得完全限定名,放入一个set中
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//根据得到的类的完全限定名,通过反射机制实例化,放入list
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
2 执行run方法
public ConfigurableApplicationContext run(String... args) {
//创建计时器对象StopWatch
StopWatch stopWatch = new StopWatch();
//开始计时
stopWatch.start();
//设置handless的属性并设置到系统属性中
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//从spring.factories获取一个监听器(EventPublishingRunListener)
SpringApplicationRunListeners listeners = getRunListeners(args);
/**
发布一个事件,若new SpringApplication()构造方法中加载的监听器对这个事件有监听,
就执行相应逻辑(观察者模式)
*/
listeners.starting();
try {
//设置换命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境对象,创建环境对象;加载系统参数;设置环境监听器集合
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//忽略一些bean的信息
configureIgnoreBeanInfo(environment);
//打印banner图
Banner printedBanner = printBanner(environment);
//创建应用程序上下文
context = createApplicationContext();
//准备异常报告期
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
/**
准备上下文环境(向上下文环境设置一些属性值)
--设置环境对象
--进行初始化操作
--发布一个监听事件,若listeners里的监听器对该事件有监听,则执行相应操作
--获取beanFactory工厂(DefaultListableBeanFactory),注册一些单例对象
--load()对应的资源(加载启动类,自动装配会用到)
*/
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
/**
调用过程和spring的refresh()一样,这里不再说明,
若不了解,请阅读本人上一篇文章ioc原理
自动装配在refresh()中的invokeBeanFactoryPostProcessors()方法中实现
tomcat在refresh()中的onRefresh()方法中的createWebServer()实现
关于自动装配请看本人下一篇文章
*/
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, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
//未完待续,自动装配请看本人下一篇文章