官方文档地址
提供一种方便的启动spring应用的方式
使用run()
方法用来启动Spring应用,即创建一个Spring上下文(返回值)
SpringApplication.run(MyApplication.class,args)
其中MyApplication.class
必须是加了@SpringBootApplication
或Configuration
注解的类,args
为启动时的命令行参数。main
方法的类是java程序的入口类,在这个入口类中启动了Spring应用。下面的例子是在内部类中使用了@SpringBootApplication
,注意内部类初始化需要外部类的实例,所以需要声明为static
public class AjaxApplication {
public static void main(String[] args) {
SpringApplication.run(Test.class,args);
}
@SpringBootApplication
public static class Test{
}
}
启动顺序
- 创建一个应用上下文实例
- 注册
CommandLinePropertySource
将命令行参数转化为Spring属性 - 刷新应用上下文,载入所有单例bean
- 触发所有
CommandLineRunner
bean
启动失败
FailureAnalyzers
能够可能为你提供一份详细的错误报告和解决方法,可以实现FailureAnalyzer
来定制
定制SpringApplication
默认SpringApplication
无法满足要求时可以自己定制,直接new SpringApplication(MySpringConfiguration.class)
并使用各种set方法进行定制化,或者使用其builder方式SpringApplicationBuilder
使代码更简洁且可以垂直的使用其子类和父类的方法进行定制;
应用事件(Events)和监听(Listeners)
有些Event的触发是在SpringApplication
创建之前的,因此这部分事件无法声明为bean去起作用,需要在SpringApplication
创建时去手动添加监听器,或者在META-INF/spring.factories
文件中配置监听器,并以org.springframework.context.ApplicationListener
为key
应用事件的发生顺序如下:
ApplicationStartingEvent
在run时但未进行任何操作之前(除非监听器的注册和初始化)ApplicationEnvironmentPreparedEvent
确定应用上下文使用的Environment
且上下文创建之前ApplicationPreparedEvent
定义的bean被装载之后但在应用上下文refresh
之前ApplicationStartedEvent
应用上下文刷新后但在所有应用和command-line
回调之前ApplicationReadyEvent
所有应用和command-line
线程已经完成调用,标志着应用已经准备好服务请求ApplicationFailedEvent
启动时抛出异常时
应用事件的发送采用spring发布模式,子上下文的事件监听器也会发布到父上下文,因此如果应用采用垂直SpringApplication实例,一个监听器可能会受到许多相同应用事件类型的实例。为了区分监听器来自哪个应用上下文,context应该可以被注入并与事件上下文做比较。context注入可以采用ApplicationContextAware
或者当监听器是一个bean时可以使用@Autowired
推断网络环境
- 如果存在类
org.springframework.web.reactive.DispatcherHandler
且不存在类org.springframework.web.servlet.DispatcherServlet
则使用AnnotationConfigReactiveWebServerApplicationContext
- 当不存在
org.springframework.web.servlet.DispatcherServlet
或javax.servlet.Servlet
时将设置为AnnotationConfigApplicationContext
- 当存在SpringMVC时为
AnnotationConfigServletWebServerApplicationContext
- 可以在SpringApplication中设置网络环境
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
return REACTIVE;
} else {
String[] var0 = SERVLET_INDICATOR_CLASSES;
int var1 = var0.length;
for(int var2 = 0; var2 < var1; ++var2) {
String className = var0[var2];
if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
return NONE;
}
}
return SERVLET;
}
}
应用参数
ApplicationArguments
来操作run()
方法中的参数
import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
@Component
public class MyBean {
@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}
}
ApplicationRunner or CommandLineRunner
在SpringApplication
启动后运行一次个性化代码,可以实现ApplicationRunner
或者 CommandLineRunner
接口,只有一个run方法在SpringApplication.run(…)
完成之前被调用
CommandLineRunner
提供访问应用参数作为一个简单的String数组,代码如下:
import org.springframework.boot.*;
import org.springframework.stereotype.*;
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
可以实现org.springframework.core.Ordered接口来定义执行顺序
ApplicationRunner使用参数ApplicationArguments
应用退出
每个SpringApplication
都在JVM上注册有一个关闭的钩子来保证优雅的关闭,从而有时间能够调用相关回调函数(如DisposableBean
接口 或 @PreDestroy
注解表示的方法)
beans可以实现org.springframework.boot.ExitCodeGenerator
来自定义exit code并可以将之传递到System.exit()
@SpringBootApplication
public class ExitCodeApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args)));
}
}
getExitCode()
之处抛出异常时返回的exit code