环境
上配置
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.0'
id 'io.spring.dependency-management' version '1.1.5'
}
group = 'org.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
}
上代码,注意启动是从SpringApplication
静态方法开始的,传递了两个参数,目前args
为空
@SpringBootApplication
public class DemoxApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DemoxApplication.class, args);
}
}
springboot
启动
这里先是实例化了SpringApplication
然后调用了实例方法run
new SpringApplication(primarySources).run(args);
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 判断应用类型 java程序,web服务,还是reactive web 服务
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
通过native
方法去找对应容器的类是不是存在,如果连jakarta.servlet.Servlet
和org.springframework.web.context.ConfigurableWebApplicationContext
这两个接口都找不到,那就是普通java
程序,而不是web
程序,此时 this.webApplicationType=WebApplicationType.NONE
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;
}
public ConfigurableApplicationContext run(String... args) {
ConfigurableApplicationContext context = null;
//根据webApplicationType 使用DefaultApplicationContextFactory创建对应类型的容器
context = createApplicationContext();
}
调用了getFromSpringFactories
方法
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
try {
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,
this::createDefaultApplicationContext);
}
catch (Exception ex) {
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
+ "you may need a custom ApplicationContextFactory", ex);
}
}
先通过springboot
的spi
机制去spring.factories
文件中找 ApplicationContextFactory.class
的子类,找到了就调用对应类的ApplicationContextFactory::create
方法,找不到就使用createDefaultApplicationContext
提供的默认容器
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
getClass().getClassLoader())) {
T result = action.apply(candidate, webApplicationType);
if (result != null) {
return result;
}
}
return (defaultResult != null) ? defaultResult.get() : null;
}
分别看看这两个类的create
方法,如果WebApplicationType
匹配就走自己的createContext
方法创建容器
class ServletWebServerApplicationContextFactory implements ApplicationContextFactory {
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.SERVLET) ? null : createContext();
}
private ConfigurableApplicationContext createContext() {
if (!AotDetector.useGeneratedArtifacts()) {
return new AnnotationConfigServletWebServerApplicationContext();
}
return new ServletWebServerApplicationContext();
}
}
class ReactiveWebServerApplicationContextFactory implements ApplicationContextFactory {
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.REACTIVE) ? null : createContext();
}
private ConfigurableApplicationContext createContext() {
if (!AotDetector.useGeneratedArtifacts()) {
return new AnnotationConfigReactiveWebServerApplicationContext();
}
return new ReactiveWebServerApplicationContext();
}
}
我这里没有引入对应的web
容器依赖包,所以都没有,而是走的默认容器
private ConfigurableApplicationContext createDefaultApplicationContext() {
if (!AotDetector.useGeneratedArtifacts()) {
return new AnnotationConfigApplicationContext();
}
return new GenericApplicationContext();
}
所以可以得出结论,如果没有引入对应web容器包的时候,springboot
使用的就是AnnotationConfigApplicationContext
容器
最简单的模式试过了,加个web
依赖看看效果
implementation 'org.springframework.boot:spring-boot-starter-web:3.1.2'
这个时候 this.webApplicationType=WebApplicationType.SERVLET
,最终得到的容器就是AnnotationConfigServletWebServerApplicationContext
了