SpringBoot SpringApplication底層原始碼分析與自動裝配
目錄
丟擲問題
@SpringBootApplication
public class LearnspringbootApplication {
public static void main(String[] args) {
SpringApplication.run(LearnspringbootApplication.class, args);
}
}
大家可以看到,如上所示是一個很常見的SpringBoot啟動類,我們可以看到僅僅使用了一個Main方法就啟動了整個SpringBoot專案是不是很神奇,下面我們來仔細剖析以下這一段程式碼,這段程式碼中我們可以仔細地觀察到最重要的兩個部分,分別是@SpringBootApplication
SpringApplication
這個類。
- @SpringBootApplication註解
- SpringApplication類
@SpringBootApplication註解剖析
開啟這個@SpringBootApplication
註解,如下所示
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { @AliasFor(annotation = EnableAutoConfiguration.class) Class<?>[] exclude() default {}; @AliasFor(annotation = EnableAutoConfiguration.class) String[] excludeName() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {}; }
我們可以發現;我們可以在@SpringBootApplication
註解中使用exclude()
,excludeName()
,scanBasePackages()
,scanBasePackageClasses()
這四個方法來進行自定義我們需要排除裝配的Bean,掃描包路徑,掃描類路徑。
搭眼一瞅,在@SpringBootApplication
註解上還有下面那麼多註解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
這四個註解不用看,就是關於註解的一些定義
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
註解我們點進去看一下,發現是下面這個樣子,@SpringBootConfiguration註解上又標註了@Configuration註解,想必在@Configuration註解上也標註了@Component註解,這不就是我們上一章節說的Spring的模式註解。總的來說嘛,SpringBootConfiguration註解的作用就是把類變成可以被Spring管理的Bean
結論 1 :也就是說標註
@SpringBootApplication
註解的類會成為Spring的Bean
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
我們再來看一下@EnableAutoConfiguration
,從名字上我們就可以看到“啟用自動裝配”
的意思。那我們可要仔細看一下。從下面我們可以看到只有兩個我們需要了解的註解,分別是@AutoConfigurationPackage
和@Import
註解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
當我點進去@AutoConfigurationPackage
註解中,發現該註解又啟用了一個模組裝配@Import(AutoConfigurationPackages.Registrar.class)
(上一章節有講到);所以又點進去AutoConfigurationPackages.Registrar.class
這個類,發現這個類又實現了兩個介面ImportBeanDefinitionRegistrar
和DeterminableImports
在該類的實現方法中的PackageImport()
;最後終於發現了下面這段程式碼。
PackageImport(AnnotationMetadata metadata) {
this.packageName = ClassUtils.getPackageName(metadata.getClassName());
}
結論 2 :SpringBoot預設會裝配啟動類路徑的所有包下可裝配的Bean;也就是說如果你把SpringBoot啟動類放在一個單獨的包中,則SpringBoot不會裝配到你的其他Bean。這時候你就要使用
@SpringBootApplication
的scanBasePackages()
方法進行另行配置。
此時@EnableAutoConfiguration
註解僅僅就剩下@Import(AutoConfigurationImportSelector.class)
沒有看了,不過從註解上我們可以看到使用@Import
註解,所以可以知道SpringBoot使用的是模組裝配的介面實現方式
。所以我麼針對AutoConfigurationImportSelector
這個類仔細剖析一下。AutoConfigurationImportSelector
- > AutoConfigurationImportSelector.selectImports()
->getAutoConfigurationEntry()
-> getCandidateConfigurations()
->SpringFactoriesLoader.loadFactoryNames()
-> loadFactoryNames()
->loadSpringFactories()
; 哈哈果然原始碼不經扒;看下面原始碼;META-INF/spring.factories
這不就是配置SpringBoot自動配置的檔案嘛。
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
結論 3 :SpringBoot在啟動時會自動載入Classpth路徑下的
META-INF/spring.factories
檔案,所以我們可以將需要自動配置的Bean寫入這個檔案,SPringBoot會替我們自動裝配。這也正是配置SpringBoot自動配置的步驟。
SpringApplication類剖析
@SpringBootApplication
public class LearnspringbootApplication {
public static void main(String[] args) {
SpringApplication.run(LearnspringbootApplication.class, args);
}
}
在Main方法中我們可以看到SpringApplication作為一個啟動類來啟動SpringBoot應用程式。那麼SpringApplication類是如何進行啟動整個應用程式的呢?
第一步:配置SpringBoot Bean來源
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
從SpringApplication類的構造方法中我們可以看到,這裡傳入了一個主Bean來源;因為我們將標註了@SpringBootApplication
註解的LearnspringbootApplication.class
傳遞了進來,所以@SpringBootApplication
掃描到的Bean和自動裝配的Bean會作為主Bean來源。當然我們可以呼叫該類的setSources()
方法設定自己的SpringXML配置。
第二步 :自動推斷SpringBoot的應用型別
this.webApplicationType = WebApplicationType.deduceFromClasspath();
從上面一句程式碼(既SpringApplication初始化方法中一行程式碼);我們觀察deduceFromClasspath()
方法可以看到,SpringBoot判斷類路徑下是否存在下面類進而判斷SpringBoot的應用型別。三種類型分別是NONE
,SERVLET
,REACTIVE
。當然我們也可以呼叫setWebApplicationType()
自行設定。
private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
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";
private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
第三步:推斷SpringBoot的引導類
this.mainApplicationClass = deduceMainApplicationClass();
從上面一句程式碼(既SpringApplication初始化方法中一行程式碼);我們可以通過deduceMainApplicationClass()
方法可以看到SpringBoot根據Main 執行緒執行堆疊判斷實際的引導類。(PS:存在一種情況就是標註@SpringBootApplication
註解的並不是引導類情況)
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;
}
第四步:載入應用上下文初始化器
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
從上面一句程式碼(既SpringApplication初始化方法中一行程式碼);我們發現setInitializers()
方法會呼叫getSpringFactoriesInstances()
-> getSpringFactoriesInstances()
-> getSpringFactoriesInstances()
該方法會使用SpringFactoriesLoader
類記進行載入配置資源既META-INF/spring.factories
,利用 Spring 工廠載入機制,例項化 ApplicationContextInitializer 實現類,並排序物件集合。並使用AnnotationAwareOrderComparator
類的sort()
方法進行排序。
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// 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;
}
第五步 :載入應用事件監聽器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
從上面一句程式碼(既SpringApplication初始化方法中一行程式碼);從setListeners()
方法中可以看到該方法仍然呼叫getSpringFactoriesInstances()
方法,不同的是利用 Spring 工廠載入META-INF/spring.factories
,例項化 ApplicationListener
實現類,並排序物件集合
第六步:啟動SpringApplication 執行監聽器( SpringApplicationRunListeners )
從SpringApplication
類的run()
方法中,我們可以看到下面程式碼getRunListeners()
方法同樣利用 Spring 工廠載入機制,讀取 SpringApplicationRunListener 物件集合,並且封裝到組合類
SpringApplicationRunListeners物件中並啟動執行監聽器。
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
第七步:監聽SpringBoot/Spring事件
Spring Boot 通過 SpringApplicationRunListener 的實現類 EventPublishingRunListener 利用 Spring Framework 事件
API ,廣播 Spring Boot 事件。
第八步:建立SpringBoot的應用上下文
context = createApplicationContext();
從SpringApplication
類的run()
方法中,我們可看到createApplicationContext()
根據第二步推斷的SpringBoot應用型別建立相應的上下文。
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
根據推斷的SpringBoot應用型別建立下面三種之一的上下文
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
+ "annotation.AnnotationConfigApplicationContext";
public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
+ "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";
public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework."
+ "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";
第九步:建立 Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
從SpringApplication
類的run()
方法中,我們可看到prepareEnvironment()
根據第二步推斷的SpringBoot應用型別建立相應的上下文。建立不同的Environment
。從下面可以看到他們分別是StandardServletEnvironment
,StandardReactiveWebEnvironment
,StandardEnvironment
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
結論
標註
@SpringBootApplication
註解的類會成為Spring的BeanSpringBoot預設會裝配啟動類路徑的所有包下可裝配的Bean;也就是說如果你把SpringBoot啟動類放在一個單獨的包中,則SpringBoot不會裝配到你的其他Bean。這時候你就要使用
@SpringBootApplication
的scanBasePackages()
方法進行另行配置。SpringBoot在啟動時會自動載入Classpth路徑下的
META-INF/spring.factories
檔案,所以我們可以將需要自動配置的Bean寫入這個檔案。同樣SpringBoot也會掃描Jar包中的META-INF/spring.factories
檔案;例如當匯入spring-boot-starter
起步依賴的時候,並且啟用了自動裝配註解@EnableAutoConfiguration
,就將會替我們自動裝配如如下類;如果滿足條件的話。org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\ org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\ org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\ org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\ org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\ org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\ org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\ org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\ org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\ org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\ org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\ org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\ org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\ org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\ org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\ org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
該教程所屬Java工程師之SpringBoot系列教程,本系列相關博文目錄 Java工程師之SpringBoot系列教程前言&目錄