第三章:理解SpringApplication
第一节:基础技术和衍生技术
学好spirngboot,一定要学好spring framework
基础技术(spring framework)
- spring 模式注解
- spirng 应用上下文
- spring 工厂加载机制
- spring 应用上下文初始器
- spring Environment 抽象接口
- spirng 应用事件/监听器
衍生技术(spring boot )
- SpringApplication
- SpringApplication Builder API
- SpringApplication 运行监听器
- SpringApplication 参数
- SpringApplication 故障分析
- Spring Boot 应用事件/监听器
第二节:SpringApplication 准备阶段
定义
- spring应用引导类,提供便利的自定义行为方法
场景
- 嵌入式web应用和非web应用(非嵌入式web server则失效,现在版本不知道支持不)
运行
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
自定义SpringApplication
-
通过
SpringApplicationBuilder
调整public class MyApplication { public static void main(String[] args) { new SpringApplicationBuilder() .sources(ApplicationBoot.class)//这样配置源,不一定是主方法,但是其他方式必须是@SpringBoot .run(args); } @SpringBootApplication public static class ApplicationBoot{ } }
准备阶段
//SpringApplication 构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//配置spring bean源
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//推断web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//加载应用上下文
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//加载应用事件监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推断主引导类
this.mainApplicationClass = deduceMainApplicationClass();
}
1. 配置spring bean源
- java配置class或者xml上下文配置文件集合,用于Spring Boot
BeanDefinitionLoader
读取,并且将配置源解析加载为spring bean 定义,可以一个或多个以上
1. java配置class
- 用于spring 注解驱动中java配置类,大多数情况下是spring模式注解所标注的类,如
@Configuration
2. xml上下文配置文件
- 用于spring 传统配置驱动中的xml文件
2. 推断deduce
-
推断web应用类型,根据当前应用classpath中是否存在相关实现类,来推断
- Web Reactive :
WebApplicationType.REACTIVE
- Web Servlet :
WebApplicationType.SERVLET
- 非Web :
WebApplicationType.NONE
#spring-boot-2.3.2 private WebApplicationType deduceWebApplicationType() { if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null) && !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null) && !ClassUtils.isPresent(JERSEY_WEB_ENVIRONMENT_CLASS, null)) { return WebApplicationType.REACTIVE; } for (String className : WEB_ENVIRONMENT_CLASSES) { if (!ClassUtils.isPresent(className, null)) { return WebApplicationType.NONE; } } return WebApplicationType.SERVLET; } private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext" };
- Web Reactive :
-
推断主引导类(Main Class)就是
@SpringBootApplication
注解的类,根据Main线程执行堆栈判断实际的引导类heap 堆 stack栈 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; }
3. 加载
-
加载应用上下文初始器
ApplicationContextInitializer
-
利用spring工程加载机制,实例化
ApplicationContextInitializer
实现类,并排序对象集合private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates //spring工厂类加载器 //第一步:实现,加载实现类 Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); //第三步:排序 AnnotationAwareOrderComparator.sort(instances); return instances; }
//spring工厂类加载器 public final class SpringFactoriesLoader { /** * The location to look for factories. * <p>Can be present in multiple JAR files. */ //第二步:配置资源 public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class); private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>(); }
#spring-boot-autoconfigure-2.3.3.RELEASE.jar!/META-INF/spring.factories # Initializers 初始化器 #应用上下文初始化器 org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.autoconfigure.BackgroundPreinitializer # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
-
-
加载应用事件监听器
ApplicationListener
- 具体步骤同上
第三节:SpringApplication 运行阶段
1. 加载SpringApplication
运行监听器SpringApplicationRunListeners
- 利用spring工厂加载机制,读取
SpringApplicationRunListener
对象集合,并且封装到组合类SpringApplicationRunListeners
@SpringBootApplication
public class LCApplication {
public static void main(String[] args) {
SpringApplication.run(LCApplication.class, args);
}
}
//run()方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
//1-加载运行监视器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//2-运行监视器
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//3-创建environment,见下文创建spring environment
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
//4-创建spirng应用上下文,见下文创建spring应用上下文
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
}
//工厂类加载
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
2. 运行SpringApplication
运行监听器SpringApplicationRunListeners
监听方法 | 阶段说明 | springboot起始版本 |
---|---|---|
starting() | spring应用刚启动 | 1.0 |
environmentPrepared(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 |
//org.springframework.boot.SpringApplicationRunListeners
class SpringApplicationRunListeners {
private final Log log;
private final List<SpringApplicationRunListener> listeners;
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
this.log = log;
this.listeners = new ArrayList(listeners);
}
void starting() {
Iterator var1 = this.listeners.iterator();
while(var1.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
listener.starting();
}
}
void environmentPrepared(ConfigurableEnvironment environment) {
Iterator var2 = this.listeners.iterator();
while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
listener.environmentPrepared(environment);
}
}
void contextPrepared(ConfigurableApplicationContext context) {
Iterator var2 = this.listeners.iterator();
while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
listener.contextPrepared(context);
}
}
void contextLoaded(ConfigurableApplicationContext context) {
Iterator var2 = this.listeners.iterator();
while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
listener.contextLoaded(context);
}
}
void started(ConfigurableApplicationContext context) {
Iterator var2 = this.listeners.iterator();
while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
listener.started(context);
}
}
void running(ConfigurableApplicationContext context) {
Iterator var2 = this.listeners.iterator();
while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
listener.running(context);
}
}
void failed(ConfigurableApplicationContext context, Throwable exception) {
Iterator var3 = this.listeners.iterator();
while(var3.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var3.next();
this.callFailedListener(listener, context, exception);
}
}
}
3. 监听spring boot 事件/spring 事件
spring Framework 事件/监听器编程模型
- spring 应用事件
- 普通应用事件
Application
- 应用上下文事件:
ApplicationContextEvent
- 普通应用事件
- spring 应用监听器
- 接口编程模型:
ApplicationListener
- 注解编程模型:
@EventListener
- 接口编程模型:
- spring 应用事件广播器
- 接口:
ApplicationEventMulticaster
- 实现类:
SimpleApplicationEventMulticaster
- 执行模式:同步或异步
- 接口:
EventPublishingRunListener
监听方法与 spring boot 事件对应关系
监听方法 | springboot事件 | springboot起始版本 |
---|---|---|
starting() | ApplicationStartingEvent | 1.5 |
environmentPrepared(ConfigurableEnvironment) | ApplicationEnvironmentPreparedEvent | 1.0 |
`contextPrepared(ConfigurableApplicationContext) | ||
contextLoaded(ConfigurableApplicationContext) | ApplicationPerparedEvent | 1.0 |
started(ConfigurableApplicationContext) | ApplicationStartedEvent | 2.0 |
running(ConfigurableApplicationContext) | ApplicationReadyEvent | 2.0 |
failed(ConfigurableApplicationContext,Throwable) | ApplicationFailedEvent | 1.0 |
//org.springframework.boot.context.event.EventPublishingRunListener
//注意这里,实现了SpringApplicationRunListener接口
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
//这里构造器中的参数,为入口类传入的参数
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
Iterator var3 = application.getListeners().iterator();
while(var3.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var3.next();
this.initialMulticaster.addApplicationListener(listener);
}
}
public int getOrder() {
return 0;
}
public void starting() {
//广播器
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
public void contextLoaded(ConfigurableApplicationContext context) {
ApplicationListener listener;
for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {
listener = (ApplicationListener)var2.next();
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware)listener).setApplicationContext(context);
}
}
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
public void started(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
}
public void running(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
}
public void failed(ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
if (context != null && context.isActive()) {
context.publishEvent(event);
} else {
if (context instanceof AbstractApplicationContext) {
Iterator var4 = ((AbstractApplicationContext)context).getApplicationListeners().iterator();
while(var4.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var4.next();
this.initialMulticaster.addApplicationListener(listener);
}
}
this.initialMulticaster.setErrorHandler(new EventPublishingRunListener.LoggingErrorHandler());
this.initialMulticaster.multicastEvent(event);
}
}
}
4. 创建spring应用上下文 ConfigurableApplicationContext
根据准备阶段的推断Web应用类型,创建对应的ConfigurableApplicationContext
实例
- web reactive :
AnnotationConfigReactiveWebServerApplicatioinContext
- web servlet :
AnnotationConfigServletWebServerApplicationContext
- 非web :
AnnotationConfigApplicationContext
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch(this.webApplicationType) {
case SERVLET:
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
}
} catch (ClassNotFoundException var3) {
throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
}
}
return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
5. 创建Environment
根据准备阶段的推断Web应用类型,创建对应的ConfigurableEnvironment
实例
- web reactive :
StandardEnvironment
- web servlet :
StandardServletEnvironment
- 非web :
StandardEnvironment
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
} else {
switch(this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
}