目录
1.springboot启动类
2.run方法
3.SpringApplication构造方法
3.1 this.sources = new LinkedHashSet();
3.3 this.logStartupInfo = true;
3.4 this.addCommandLineProperties = true;
3.5 this.addConversionService = true;
3.6 this.headless = true;
3.7 this.registerShutdownHook = true;
3.8 this.additionalProfiles = Collections.emptySet();
3.9 this.isCustomEnvironment = false;
springboot最简单且最基础的启动类。接下来我们进入run方法。
@SpringBootApplication
public class DemoBckApplication {
public static void main(String[] args) {
SpringApplication.run(DemoBckApplication.class, args);
}
}
可以看到返回的是(new SpringApplication(primarySources)).run(args); 这里先将启动类传入的class参数转成数组对象,再传入SpringApplication类的构造方法。那我们先看一下SpringApplication类的构造方法,看看里面初始化了哪些属性。
//primarySource参数:DemoBckApplication.class
public static ConfigurableApplicationContext run(Class> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
附一张debugger的图,SpringApplication初始化的属性都在里面了。然后我们来看看部分属性的含义和用途,大概了解即可,具体的我们待会看代码分析。
aa
该属性是用来打印springboot启动时的图标。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.3.3.RELEASE)
Mode是org.springframework.boot.Banner类中静态enum类型。 OFF:关闭 CONSOLE:打印在控制台 LOG:打印到日志
true的话则打印jvm的启动和运行信息。包括启动类、java版本、pid等
通过命令行参数向application.properties中添加属性配置,例如执行java -jar test.jar –server.port=9000,将向application.properties中新增一个属性配置。
加载默认的类型转换和格式化类 (ApplicationConversionService)
public static void addApplicationConverters(ConverterRegistry registry) {
addDelimitedStringConverters(registry);
registry.addConverter(new StringToDurationConverter());
registry.addConverter(new DurationToStringConverter());
registry.addConverter(new NumberToDurationConverter());
registry.addConverter(new DurationToNumberConverter());
registry.addConverter(new StringToPeriodConverter());
registry.addConverter(new PeriodToStringConverter());
registry.addConverter(new NumberToPeriodConverter());
registry.addConverter(new StringToDataSizeConverter());
registry.addConverter(new NumberToDataSizeConverter());
registry.addConverter(new StringToFileConverter());
registry.addConverter(new InputStreamSourceToByteArrayConverter());
registry.addConverterFactory(new LenientStringToEnumConverterFactory());
registry.addConverterFactory(new LenientBooleanToEnumConverterFactory());
if (registry instanceof ConversionService) {
addApplicationConverters(registry, (ConversionService)registry);
}
}
public static void addApplicationFormatters(FormatterRegistry registry) {
registry.addFormatter(new CharArrayFormatter());
registry.addFormatter(new InetAddressFormatter());
registry.addFormatter(new IsoOffsetFormatter());
}
开启java的headless模式。此模式允许java在没有显示器、鼠标等设备缺失的情况下启动服务,对于部署在服务器的程序来说是很有必要的。
System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
创建线程,该线程用来在java程序关闭后释放资源(即Spring Shutdown Hook)
//启动类方法
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
} catch (AccessControlException var3) {
}
}
this.refresh((ApplicationContext)context);
}
//创建线程
public void registerShutdownHook() {
if (this.shutdownHook == null) {
this.shutdownHook = new Thread("SpringContextShutdownHook") {
public void run() {
synchronized(AbstractApplicationContext.this.startupShutdownMonitor) {
AbstractApplicationContext.this.doClose();
}
}
};
//线程注册
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
//关闭
protected void doClose() {
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Closing " + this);
}
if (!NativeDetector.inNativeImage()) {
LiveBeansView.unregisterApplicationContext(this);
}
try {
// 发布Spring 应用上下文的关闭事件,让监听器们有机会在应用关闭之前做出一些响应
this.publishEvent((ApplicationEvent)(new ContextClosedEvent(this)));
} catch (Throwable var3) {
this.logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", var3);
}
if (this.lifecycleProcessor != null) {
try {
// 执行lifecycleProcessor的关闭方法,让Lifecycle们有机会在应用关闭之前做出一些响应
this.lifecycleProcessor.onClose();
} catch (Throwable var2) {
this.logger.warn("Exception thrown from LifecycleProcessor on context close", var2);
}
}
// 销毁IOC容器里所有单例Bean
this.destroyBeans();
// 关闭BeanFactory
this.closeBeanFactory();
// 勾子函数,让子类实现后做各自的资源清理,比如ServletWebServerApplicationContext会实现该勾子函数关闭内嵌的WebServer(Tomcat)
this.onClose();
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
this.active.set(false);
}
}
默认为空,即使用springboot默认配置文件。可以调用 SpringApplication的setAdditionalProfiles()实现spring boot的profile指定,根据指定参数不同读取“dev”、“test”等不同环境的配置。如果是在配置文件中配置spring.profiles.active: dev,读取配置的方法在后面的run方法中,文章后面进行介绍。
private void configureAdditionalProfiles(ConfigurableEnvironment environment) {
//如果additionalProfiles不为空,则获取配置并设置
if (!CollectionUtils.isEmpty(this.additionalProfiles)) {
//获取spring.profiles.active 配置
Set profiles = new LinkedHashSet(Arrays.asList(environment.getActiveProfiles()));
if (!profiles.containsAll(this.additionalProfiles)) {
profiles.addAll(this.additionalProfiles);
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
}
}
}
加载环境配置
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
//创建默认环境配置
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
//加载默认的类型转换和格式化类
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
//默认配置放入ConfigurationPropertySources
ConfigurationPropertySources.attach((Environment)environment);
listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
//读取application配置文件并加载
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
//将application配置放入,并提高至最高优先级
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}