1. 综述
HttpHandlerAutoConfiguration中类,把HttpHandler注册成了一个bean,注册bean的时候需要applicationContext(详情参见第二节),applicationContext又是如何实例化的呢,下面我们就来分析一下。
2. SpringApplication 实例化context过程
2.1 SpringApplicatin 类中的run方法
applicationContext是在SpringApplication方法中实例化的,run方法是入口,它负责根据指定的args参数启动spring,具体代码如下所示:
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { return new SpringApplication(primarySources).run(args); }
2.2 run方法的具体实现
run方法的具体实现如下所示,从源码中可知,context是ConfigurableApplicationContext类型,通过调用方法createApplicationContext()生成。
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext(); //这一行代码
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
2.3 createApplicationContext() 方法
createApplicationContext() 方法代码如下所示,通过applicationContextFactory.create()方法创建,方法需要WebApplicationType类型的入参
protected ConfigurableApplicationContext createApplicationContext() { return this.applicationContextFactory.create(this.webApplicationType); }
当WebApplicationType为REACTIVE时,创建的ApplicatinContext 类型是 AnnotationConfigReactiveWebServerApplicationContext()
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.REACTIVE) ? null
: new AnnotationConfigReactiveWebServerApplicationContext();
}
webApplicationType又是如何获取的呢?
2.4. webApplicationType的获取
WebApplicationType类型实例化,是在SpringApplication构造方法中实现的,通过调用方法WebApplicationType.deduceFromClasspath();
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
2.5 WebApplicationType.deduceFromClasspath();
deduceFromClasspath()方法根据 WEBFLUX_INDICATOR_CLASS 或者 WEBMVC_INDICATOR_CLASS来决定返回那个对象
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
2.6 三个INDICATOR_CLASS定义
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";