SpringApplication 基本使用
SpringApplication.run(SpringBootApplication.class, args)
自定义SpringApplication
- 通过
SpringApplication
API调整
SpringApplication springApplication = new SpringApplication(SpringBootApplication.class);
springApplication.setBannerMode(Banner.Mode.CONSOLE);
springApplication.setWebApplicationType(WebApplicationType.NONE);
springApplication.setAdditionalProfiles("prod");
springApplication.setHeadless(true);
- 通过
SpringApplicationBuilder
API调整
new SpringApplicationBuilder(SpringBootApplication.class)
.bannerMode(Banner.Mode.CONSOLE)
.web(WebApplicationType.NONE)
.profiles("prod")
.headless(true)
.run(args);
SpringApplication 准备阶段
配置Spring Boot Bean 源
Java 配置 Class 或 XML 上下文配置文件集合,用于 Spring Boot BeanDefinitionLoader 读取 ,并且将配置源解析加载为
Spring Bean 定义 数量:一个或者多个
- Java配置Class
用于 Spring 注解驱动中 Java 配置类,大多数情况是 Spring 模式注解所标注的类,如@Configuration
。 - XML上下文配置文件
用于Spring传统配置驱动中的XML文件。
推断Web应用类型
根据当前应用ClassPath中是否存在相关实现类来判断Web应用的类型,包括:
- Web Reactive:WebApplicationType.REACTIVE
- Web Servlet: WebApplicationType.SERVLET
- 非Web:WebApplicationType.NONE
参考方法:org.springframework.boot.SpringApplication#deduceWebApplicationType
private WebApplicationType deduceWebApplicationType() {
if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
} }
return WebApplicationType.SERVLET;
}
推断引导类(Main Class)
根据 Main 线程执行堆栈判断实际的引导类
参考方法:org.springframework.boot.SpringApplication#deduceMainApplicationClass
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
加载应用上下文初始器(ApplicationContextInitializer)
利用Spring 工厂加载机制,实例化ApplicationContextInitializer实现类,并排序对象集合。
- 实现
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
@Order(Ordered.HIGHEST_PRECEDENCE)
public class HelloWorldApplicationContextInitializer<C extends ConfigurableApplicationContext>
implements ApplicationContextInitializer<C> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("HelloWorldConfigurableApplicationContext.id = "+applicationContext.getId());
}
}
public class AfterHelloWorldApplicationContextInitializer<C extends ConfigurableApplicationContext>
implements ApplicationContextInitializer<C>,Ordered {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("AfterConfigurableApplicationContext.id = "+applicationContext.getId());
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
- 技术
- 实现类:
org.springframework.core.io.support.SpringFactoriesLoader
- 配置资源:
META-INF/spring.factories
- 排序:
AnnotationAwareOrderComparator#sort
- 实现类:
加载应用事件监听器(ApplicationListener)
利用 Spring 工厂加载机制,实例化 ApplicationListener
实现类,并排序对象集合
@Order(Ordered.HIGHEST_PRECEDENCE)
public class HelloWorldApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("HelloWorldLister= "+event.getApplicationContext().getId()+","+"timestamp = "+event.getTimestamp());
}
}
代码验证listener 启动顺序(配置文件启动监听ConfigFileApplicationListener之前则无法获取到配置内容)
public class BeforeConfigFileApplicationListener implements SmartApplicationListener,Ordered {
@Override
public int getOrder() {
// return Ordered.HIGHEST_PRECEDENCE + 9;
//优先级更高 则无法加载到配置,结果为null
return ConfigFileApplicationListener.DEFAULT_ORDER -1;
}
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
|| ApplicationPreparedEvent.class.isAssignableFrom(eventType);
}
@Override
public boolean supportsSourceType(Class<?> aClass) {
return true;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
// onApplicationEnvironmentPreparedEvent(
// (ApplicationEnvironmentPreparedEvent) event);
ApplicationEnvironmentPreparedEvent preparedEvent = (ApplicationEnvironmentPreparedEvent)event;
Environment environment = preparedEvent.getEnvironment();
System.out.println("environment property :"+environment.getProperty("name"));
}
// if (event instanceof ApplicationPreparedEvent) {
// onApplicationPreparedEvent(event);
// }
}
}
SpringApplication 运行阶段
加载SpringApplication
运行监听器(SpringApplicationRunListener
)
利用 Spring 工厂加载机制,读取 SpringApplicationRunListener 对象集合,并且封装到组合类
SpringApplicationRunListener
public class HelloWorldRunListener implements SpringApplicationRunListener {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
public HelloWorldRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
@Override
public void starting() {
System.out.println("starting");
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
System.out.println("environmentPrepared");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("contextPrepared");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("contextLoaded");
}
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("started");
}
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("running");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("failed");
}
}
运行SpringApplication
运行监听器( SpringApplicationRunListener
)
SpringApplicationRunListener
监听多个运行状态方法:
监听方法 | 阶段说明 | Spring Boot起始版本 |
---|---|---|
starting() | Spring应用刚启动 | 1.0 |
enviromentPrepared(ConfigurableEnvironment) | ConfigurableEnvironment准备妥当,允许将其调整 | 1.0 |
contextPrepared(ConfigurableApplicationContext) | ConfigurableApplicationContext准备妥当,允许将其调整 | 1.0 |
contextLoaded(ConfigurableApplicationContext) | ConfigurableApplicationContext已装载,但仍未启动 | 1.0 |
started(ConfigurableApplicationContext) | ConfigurableApplicationContext已启动,此时 Spring Bean 已初始化完成 | 2.0 |
running(ConfigurableApplicationContext) | Spring应用正在运行 | 2.0 |
failed(ConfigurableApplicationContext,Throwable) | Spring 应用运行失败 | 2.0 |
监听 Spring Boot 事件 / Spring 事件
Spring Boot 通过 SpringApplicationRunListener
的实现类 EventPublishingRunListener
利用 Spring Framework 事件
API ,广播 Spring Boot 事件。
Spring Framework 事件/监听器编程模型
- Spring 应用事件
- 普通应用事件:
ApplicationEvent
- 应用上下文事件:
ApplicationContextEvent
- 普通应用事件:
- Spring 应用监听器
- 接口编程模型:
ApplicationListener
- 注解编程模型:
@EventListener
- 接口编程模型:
- Spring 应用事广播器
- 接口:
ApplicationEventMulticaster
- 实现类:
SimpleApplicationEventMulticaster
执行模式:同步或异步
- 接口:
public class SpringApplicationEventBootstrap {
public static void main(String[] args) {
//创建上下文 非WEB应用上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//注册应用事件监听器
context.addApplicationListener(event -> {
System.out.println("监听到事件:"+event);
});
//启动上下文
context.refresh();
//发布事件
context.publishEvent("HelloWorld");//PayloadApplicationEvent
context.publishEvent("2018");
context.publishEvent(new ApplicationEvent("Zed"){} );//ApplicationEvent
//关闭上下文
context.close();
}
}
EventPublishingRunListener监听方法与 Spring Boot 事件对应关系
监听方法 | SpringBoot事件 | Spring Boot起始版本 |
---|---|---|
starting() | ApplicationStartingEvent | 1.5 |
enviromentPrepared(ConfigurableEnvironment) | ApplicationEnvironmentPreparedEvent | 1.0 |
contextPrepared(ConfigurableApplicationContext) | ||
contextLoaded(ConfigurableApplicationContext) | ApplicationPreparedEvent | 1.0 |
started(ConfigurableApplicationContext) | ApplicationStartedEvent | 2.0 |
running(ConfigurableApplicationContext) | ApplicationReadyEvent | 2.0 |
failed(ConfigurableApplicationContext,Throwable) | ApplicationFailedEvent | 1.0 |
创建Spring应用上下文(ConfigurableApplicationContext
)
根据准备阶段的推断 Web 应用类型创建对应的 ConfigurableApplicationContext
实例:
- Web Reactive:
AnnotationConfigReactiveWebServerApplicationContext
- Web Servlet:
AnnotationConfigServletWebServerApplicationContext
- 非 Web:
AnnotationConfigApplicationContext
创建 Environment
根据准备阶段的推断 Web 应用类型创建对应的 ConfigurableEnvironment
实例:
- Web Reactive:
StandardEnvironment
- Web Servlet:
StandardServletEnvironment
- 非 Web:
StandardEnvironment
代码解释:
@SpringBootApplication
public class SpringApplicationContextBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(SpringApplicationContextBootstrap.class)
.web(WebApplicationType.NONE)
// .web(WebApplicationType.REACTIVE)
.web(WebApplicationType.SERVLET)
.run(args);
System.out.println("ConfigurableApplicationContext 类型:"+context.getClass().getName());
System.out.println("Environment 类型:"+context.getEnvironment().getClass().getName());
context.close();
}
}