1、启动流程:
SpringApplication.run(BootWebApplication.class, args);
SpringApplication类public ConfigurableApplicationContext run(String... args) 核心方法:
public ConfigurableApplicationContext run(String... args) {
//计时器
StopWatch stopWatch = new StopWatch();
// 记录当前服务开始启动
stopWatch.start();
// 上下文context,非常关键
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 给系统设置headless属性值
configureHeadlessProperty();
//listeners
// 就是通过SpringFactoriesLoader 获取到所有SpringApplicationRunListener.class的对象
// 其中args是用来进行实例化SpringApplicationRunListener对应的对象的构造器参数
// 最后返回listener是整个系统的监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 默认程序参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//environment
// 准备运行的环境上下文
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
// 打印banner,默认输出当前springboot版本等内容,可以自定义设置文本或者图片
// 具体看下面的方法详解
Banner printedBanner = printBanner(environment);
// 创建SpringBoot最重要的上下文容器
context = createApplicationContext();
/*SpringFactoriesLoader.loadFactoryNames(type, classLoader)SpringBoot框架中从类路径jar包中读取特定文件实现扩展类的载入
将所有Jar中的spring.factories(A.jar(spring.factories)*/
//使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[]{ConfigurableApplicationContext.class}, context);
// 看名称就是对context的前置准备工作,细节在后面说
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 核心方法 创建注册Bean 一级二级三级缓存 依赖注入
// 切入到spring framework的方式去完成context内容的装载
// 如果需要注册终止钩子,则注册一个
refreshContext(context);
//初始化接口 ApplicationRunner/CommandLineRunner
// 基本上认为springboot所需的服务都加载完成,进行最后的处理操作
afterRefresh(context, applicationArguments);
//表示SpringBoot服务启动步骤完成,统计下启动时间等操作
stopWatch.stop();
if (this.logStartupInfo) {
// 打印SpringBoot启动成功的消息,例如 Started xxx in 12.4 seconds 等信息
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
//监听器正式启动
listeners.started(context);
//初始化实现的接口启动
callRunners(context, applicationArguments);
} catch (Throwable ex) {
// 启动失败了就会输出Application startup failed 日志
// 并且会输出具体的错误内容信息
handleRunFailure(context, ex, exceptionReporters, listeners);
}throw new IllegalStateException(ex);
}
2、解决依赖注入
refreshContext(context);
applicationContext.refresh();
AbstractApplicationContext:
refresh();
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
仅对于单例而言解决循环依赖:
DefaultSingletonBeanRegistry类:
singletonObjects对应一级缓存,earlySingletonObjects对应二级缓存,singletonFactories对应三级缓存。
调用applicationContext.getBean(xx)方法,最终会调到AbstractBeanFactory类的doGetBean方法;
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
上面getSingleton方法的逻辑是:
先从singletonObjects(一级缓存)中获取实例,如果可以获取到则直接返回singletonObject实例。
如果从singletonObjects(一级缓存)中获取不对实例,再从earlySingletonObjects(二级缓存)中获取实例,如果可以获取到则直接返回singletonObject实例。
如果从earlySingletonObjects(二级缓存)中获取不对实例,则从singletonFactories(三级缓存)中获取singletonFactory,如果获取到则调用getObject方法创建实例,把创建好的实例放到earlySingletonObjects(二级缓存)中,并且从singletonFactories(三级缓存)删除singletonFactory实例,然后返回singletonObject实例。
如果从singletonObjects、earlySingletonObjects和singletonFactories中都获取不到实例,则singletonObject对象为空。