虽然golang开始在后台开发横行,但是springboot还是目前大多数企业使用的技术栈。由于其成熟性,丰富的组件以及生态环境,是很多公司的首选。学习springboot需要了解其启动过程,对原理的理解可以避免停留在CRUD层面,对底层有很多深入的理解可以助力我们成长,解决深层次问题。
- 先看一下个简单的demo, 通过ideal创建的工程就会自动生成。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2.SpringApplication构造函数
代码语言:javascript复制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类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 创建ApplicationContextInitializer并初始化
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// ApplicationListener 初始化
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 运行的主类
this.mainApplicationClass = deduceMainApplicationClass();
}
3.run函数
代码语言:javascript复制public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
// 类加载上线文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
// 获取构造函数中创建的listener
SpringApplicationRunListeners listeners = getRunListeners(args);
// 开始监听
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//参数承载类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//配置环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
// 打印banner
Banner printedBanner = printBanner(environment);
//创建主的Bean
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//初始化工作
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//刷新
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 初始化监听完成
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
//进入准备阶段
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
4.prepareContext 资源加载,并且初始化。
代码语言:javascript复制private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
// 初始化资源加载设置
postProcessApplicationContext(context);
// 开始初始化
applyInitializers(context);
listeners.contextPrepared(context);
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
// 依赖注入
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
// 懒加载,解决循环依赖问题
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//加载初始化bean,IOC的实现
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
5.refresh ioc的最后一步,对bean进行后续处理。
代码语言:javascript复制public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//准备context用于刷新
prepareRefresh();
//通知子类刷新bean
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备beanfactory
prepareBeanFactory(beanFactory);
try {
// 允许beanfactory刷新子类
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 把bean注册到context中
invokeBeanFactoryPostProcessors(beanFactory);
// 注册processor用于bean的创建
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 初始化资源信息
initMessageSource();
//广播信息初始化
initApplicationEventMulticaster();
//对特殊的子类进行刷新
onRefresh();
//检查注册的bean并且监听
registerListeners();
//初始化其他类懒加载的实力
finishBeanFactoryInitialization(beanFactory);
// 发布刷新完毕的消息
finishRefresh();
}