你总说你开发了多少年,那么你会看源码吗(SpringBoot)

1、快速生成一个简单的SpringBoot项目

进入地址:

https://start.spring.io/
,点击生成代码即可。

2、注解:@SpringBootApplication

一个Web项目,只需要这一行注解。有这么厉害吗?我们一起看看它究竟做了什么?

@SpringBootApplicationpublic class SpringBootDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDemoApplication.class, args); }}复制代码

The @SpringBootApplication annotation is equivalent to using @Configuration , @EnableAutoConfiguration , and @ComponentScan with their default attributes

@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication {复制代码

看代码,明明是 @SpringBootConfiguration 呢,怎么说是 @Configuration 呢?

2.1、注解:@SpringBootConfiguration

@Configurationpublic @interface SpringBootConfiguration { }复制代码

然后再进入到里面去,发现竟然是 Component 注解?是不是非常熟悉呢?

@Componentpublic @interface Configuration {复制代码

Spring provides further stereotype annotations: @Component , @Service , and @Controller . @Component is a generic stereotype for any Spring-managed component. @Repository , @Service, and @Controller are specializations of @Component for more specific use cases (in the persistence, service, and presentation layers, respectively)。

2.2、注解:@ComponentScan

org.springframework.boot.SpringApplication // 第1步public ConfigurableApplicationContext run(String... args) {  refreshContext(context);}// 第2步public ConfigurableApplicationContext run(String... args) {  ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); listeners.started(context); // Called after the context has been refreshed. callRunners(context, applicationArguments); } listeners.running(context); return context;}// 第3步protected void refresh(ApplicationContext applicationContext) {  Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh();}// 第4步org.springframework.context.support.AbstractApplicationContext public void refresh() throws BeansException, IllegalStateException {  // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory);}// 第5步org.springframework.context.support.PostProcessorRegistrationDelegate for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {  if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { registryProcessor.postProcessBeanDefinitionRegistry(registry); }}// 第6步org.springframework.context.annotation.ConfigurationClassPostProcessor public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {  processConfigBeanDefinitions(registry);}// 第7步public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {  do { parser.parse(candidates); }}// 第8步org.springframework.context.annotation.ConfigurationClassParser protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {  do { sourceClass = doProcessConfigurationClass(configClass, sourceClass); }}// 第9步protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)  throws IOException { // Process any @PropertySource annotations for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // Process any @ComponentScan annotations Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // Process any @Import annotations processImports(configClass, sourceClass, getImports(sourceClass), true); // Process any @ImportResource annotations AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { String[] resources = importResource.getStringArray("locations"); Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } }}// 第10步private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,  Collection<SourceClass> importCandidates, boolean checkForCircularImports) { String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames); processImports(configClass, currentSourceClass, importSourceClasses, false);}// 第11步org.springframework.boot.autoconfigure.AutoConfigurationImportSelector @Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {  AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry( autoConfigurationMetadata, annotationMetadata);}// 第12步private List<String> filter(List<String> configurations,  AutoConfigurationMetadata autoConfigurationMetadata) { for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) { invokeAwareMethods(filter); boolean[] match = filter.match(candidates, autoConfigurationMetadata); for (int i = 0; i < match.length; i++) { if (!match[i]) { skip[i] = true; candidates[i] = null; skipped = true; } } } return new ArrayList<>(result);}// 第13步protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {  return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);}// 第14步org.springframework.core.io.support.SpringFactoriesLoader public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {  List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse); return result;}// 第15步private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {  try { Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); return result; }}public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";复制代码

也就是说,其实 spring.factories 是 spring-core 的功能。

看一下 spring-boot-autoconfigure 项目里面的 spring.factories 。

# Initializersorg.springframework.context.ApplicationContextInitializer= org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer, org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener# Application Listenersorg.springframework.context.ApplicationListener= org.springframework.boot.autoconfigure.BackgroundPreinitializer# Auto Configuration Import Listenersorg.springframework.boot.autoconfigure.AutoConfigurationImportListener= org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener# Auto Configuration Import Filtersorg.springframework.boot.autoconfigure.AutoConfigurationImportFilter= org.springframework.boot.autoconfigure.condition.OnBeanCondition, org.springframework.boot.autoconfigure.condition.OnClassCondition, org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition# Auto Configureorg.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# Failure analyzersorg.springframework.boot.diagnostics.FailureAnalyzer= org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer, org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer, org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer, org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer# Template availability providersorg.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider= org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider, org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider, org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider, org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider, org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider复制代码

看到这里,是不是有一点解惑了,为什么我们什么都没有干,它就已经具备了那么多的功能。因为在项目启动的时候,已经就给我们内置了这么多的服务。

在这里给大家推荐一个Java技术交流群: 710373545里面会分享一些资深架构师录制的视频资料:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多!

3、容器在哪儿启动的?

3.1 为什么是Tomcat默认启动?

我们再回到开始的时候,为什么启动的时候看到了 Tomcat 的日志呢?

Connected to the target VM, address: '127.0.0.1:56945', transport: 'socket' . _ __ _ _ /\ / ___'_ __ _ _(_)_ __ __ _    ( ( )___ | '_ | '_| | '_ / _` |     \/ ___)| |_)| | | | | || (_| | ) ) ) ) ' | | .__|_| |_|_| |___, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: 2019-06-13 09:15:11.818 INFO 16978 --- [ main] c.e.s.SpringBootDemoApplication : Starting SpringBootDemoApplication on bogon with PID 16978 (/Users/chenyuan/Dropbox/Workspaces/IdeaProjects/spring-boot-demo/target/classes started by chenyuan in /Users/chenyuan/Dropbox/Workspaces/IdeaProjects/spring-src-leaning) 2019-06-13 09:15:11.823 INFO 16978 --- [ main] c.e.s.SpringBootDemoApplication : No active profile set, falling back to default profiles: default// 这里日志显示,有一个embedded的tomcat启动了8080端口2019-06-13 09:15:13.597 INFO 16978 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2019-06-13 09:15:13.644 INFO 16978 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2019-06-13 09:15:13.645 INFO 16978 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.14] 2019-06-13 09:15:13.653 INFO 16978 --- [ main] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/chenyuan/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.] 2019-06-13 09:15:13.752 INFO 16978 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2019-06-13 09:15:13.752 INFO 16978 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1862 ms 2019-06-13 09:15:14.018 INFO 16978 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2019-06-13 09:15:14.226 INFO 16978 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2019-06-13 09:15:14.231 INFO 16978 --- [ main] c.e.s.SpringBootDemoApplication : Started SpringBootDemoApplication in 3.007 seconds (JVM running for 3.924)# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration @Bean @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat") public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer( ServerProperties serverProperties) { return new TomcatServletWebServerFactoryCustomizer(serverProperties); }复制代码

<!-- spring-boot-demo/pom.xml --> <dependency>  <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><!-- spring-boot-starter-web/pom.xml --> <dependency>  <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId></dependency><!-- spring-boot-starters/spring-boot-starter-tomcat/pom.xml --> <dependency>  <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <exclusions> <exclusion> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-annotations-api</artifactId> </exclusion> </exclusions></dependency>复制代码

3.2 如果要指定其他的容器呢?

<dependencies>  <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency></dependencies>复制代码

把项目中Tomca的starter注释掉,引入Jetty容器即可。

这么更换后,为什么就又能引入了呢?

org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration @Configuration@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,WebAppContext.class })@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)public static class EmbeddedJetty {  @Bean public JettyServletWebServerFactory JettyServletWebServerFactory() { return new JettyServletWebServerFactory(); }}复制代码

The @ConditionalOnClass and @ConditionalOnMissingClass annotations let @Configurationclasses be included based on the presence or absence of specific classes.

这里的 Servlet.class, Server.class, Loader.class,WebAppContext.class 就是Jetty里面的包。

这里还设计了一个工厂模式,获取一个WebServer。

@FunctionalInterfacepublic interface ServletWebServerFactory { /** * Gets a new fully configured but paused {@link WebServer} instance. Clients should * not be able to connect to the returned server until {@link WebServer#start()} is * called (which happens when the {@link ApplicationContext} has been fully * refreshed). * @param initializers {@link ServletContextInitializer}s that should be applied as * the server starts * @return a fully configured and started {@link WebServer} * @see WebServer#stop() */ WebServer getWebServer(ServletContextInitializer... initializers);}复制代码

3.3 那是在什么时候初始化容器的呢?

// 第1步org.springframework.context.support.AbstractApplicationContext public void refresh() throws BeansException, IllegalStateException {  synchronized (this.startupShutdownMonitor) { try { // Initialize other special beans in specific context subclasses. onRefresh(); }}// 第2步org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext protected void onRefresh() {  super.onRefresh(); try { createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); }}// 第3步private void createWebServer() {  WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { ServletWebServerFactory factory = getWebServerFactory(); this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources();}复制代码

在看到 factory.getWebServer ,是不是就全部都串联起来了?

转载于:https://juejin.im/post/5d05ed58e51d4555fc1acc96

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值