前言
看很多springboot相关书籍,都是先讲框架,讲设计模式,讲模块,讲扩展功能,但是往往只能给读者形成一个大概的印象或者作为一本工具来用,或者作为一本面试准备书籍。所谓一知半解大概就是现在我的状态,能熟练使用,也能说出一些原理,但是没有串联起来,没法全局看问题,站在巨人的肩膀只能看到巨人的脚。
回想我工作中处理各种问题,也是从入口处,一步一步往下走,因此也准备从springboot启动main方法一步一步往下走,看springboot具体经历了什么 ,载入提炼整个springboot的框架结构。
最简单的springboot启动类
/**
* springboot原理学习项目
*/
@SpringBootApplication
public class SpringLeanApplication {
public static void main(String[] args) {
/// springboot是提供启动入口
SpringApplication.run(SpringLeanApplication.class, args);
}
}
类SpringApplication备注
* <ul>
* <li>Create an appropriate {@link ApplicationContext} instance (depending on your
* classpath)</li>
* <li>Register a {@link CommandLinePropertySource} to expose command line arguments as
* Spring properties</li>
* <li>Refresh the application context, loading all singleton beans</li>
* <li>Trigger any {@link CommandLineRunner} beans</li>
* </ul>
1. 创建ApplicationContext实例
3. 刷新上下文,加载所有的单例bean对象
2.4暂时忽略
写备注很重要,写来是看的,别只看代码,也要看备注啊
顺便说一句,作者很多,合作很重要
* @author Phillip Webb
* @author Dave Syer
* @author Andy Wilkinson
* @author Christian Dupuis
* @author Stephane Nicoll
* @author Jeremy Rickard
* @author Craig Burke
* @author Michael Simons
* @author Madhura Bhave
* @author Brian Clozel
* @author Ethan Rubinson
* @since 1.0.0
第一章 启动调用关系
// 方法1
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
// 方法2
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args); // run执行启动
}
// 方法3
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
// 方法4
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 1)web启动类型 react/servlet/非web启动
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 2)设置初始化类
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 3)设置监听
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
SpringApplication做了3件事情
- 设置web启动类型
- 加载initializer
0 = "org.springframework.boot.devtools.restart.RestartScopeInitializer"
1 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
2 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
3 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
4 = "org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer"
5 = "org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer"
6 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
7 = "org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener"
- 加载listener
0 = "org.springframework.boot.devtools.restart.RestartApplicationListener"
1 = "org.springframework.boot.devtools.logger.DevToolsLogFactory.Listener"
2 = "org.springframework.boot.ClearCachesApplicationListener"
3 = "org.springframework.boot.builder.ParentContextCloserApplicationListener"
4 = "org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor"
5 = "org.springframework.boot.context.FileEncodingApplicationListener"
6 = "org.springframework.boot.context.config.AnsiOutputApplicationListener"
7 = "org.springframework.boot.context.config.ConfigFileApplicationListener"
8 = "org.springframework.boot.context.config.DelegatingApplicationListener"
9 = "org.springframework.boot.context.logging.ClasspathLoggingApplicationListener"
10 = "org.springframework.boot.context.logging.LoggingApplicationListener"
11 = "org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener"
12 = "org.springframework.boot.autoconfigure.BackgroundPreinitializer"
第二章 SpringApplication.run()方法说明
run方法执行最终的启动过程
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
// 秒表 统计多个任务执行时长
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 后面有说明,很久以前生成验证码的时候遇到的一个问题记录了下
configureHeadlessProperty();
// 获取runlistener
SpringApplicationRunListeners listeners = getRunListeners(args);
// 推送ApplicationStartingEvent事件
listeners.starting();
try {
// 获取启动参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 方法2
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 方法3
configureIgnoreBeanInfo(environment);
// 打印banner
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
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;
}
1. headless说明
截屏2020-04-08 下午9.00.23.png2. getRunListeners说明
创建SpringApplicationRunListeners,包含以下listener
org.springframework.boot.context.event.EventPublishingRunListener
SpringApplicationRunListener内部包含ApplicationEventMulticaster,用于管理对多个ApplicationListener(参考SpringApplication初始化)推送SpringApplicationEvent事件
网友评论