SpringBoot SpringApplication底層原始碼分析與自動裝配
目錄
- @SpringBootApplication註解剖析
-
SpringApplication類剖析
- 第一步:配置SpringBoot Bean來源
- 第二步 :自動推斷SpringBoot的應用型別
- 第三步:推斷SpringBoot的引導類
- 第四步:載入應用上下文初始化器
- 第五步 :載入應用事件監聽器
- 第六步:啟動SpringApplication 執行監聽器( SpringApplicationRunListeners )
- 第七步:監聽SpringBoot/Spring事件
- 第八步:建立SpringBoot的應用上下文
- 第九步:建立 Environment
丟擲問題
@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的Bean -
SpringBoot預設會裝配啟動類路徑的所有包下可裝配的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系列教程,本系列相關博文目錄ofollow,noindex" target="_blank">Java工程師之SpringBoot系列教程前言&目錄