Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >我们如何看SpringBoot的源代码

我们如何看SpringBoot的源代码

作者头像
chengcheng222e
发布于 2021-11-04 03:41:26
发布于 2021-11-04 03:41:26
1.2K00
代码可运行
举报
文章被收录于专栏:简栈文化简栈文化
运行总次数:0
代码可运行
1、快速生成一个简单的SpringBoot项目

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

2、注解:@SpringBootApplication

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SpringBootApplication
public 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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Configuration
public @interface SpringBootConfiguration {
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public @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
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
@Override
public 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.factoriesspring-core的功能。

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
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
# Failure analyzers
org.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 providers
org.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

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

3、容器在哪儿启动的?
3.1 为什么是Tomcat默认启动?

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
@Bean
  @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
  public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
      ServerProperties serverProperties) {
    return new TomcatServletWebServerFactoryCustomizer(serverProperties);
  }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 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 如果要指定其他的容器呢?
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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容器即可。

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 @Configuration classes be included based on the presence or absence of specific classes.

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@FunctionalInterface
public 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 那是在什么时候初始化容器的呢?
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 第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,是不是就全部都串联起来了?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 简栈文化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
「数据中心」脊叶网络架构:Cisco VXLAN MP-BGP EVPN脊叶网络
在RFC 7348定义的VXLAN泛洪学习模式下,终端主机信息学习和VTEP发现都是基于数据平面的,没有控制协议在VTEP之间分配终端主机可达性信息。为了克服flood的局限性并学习VXLAN,Cisco VXLAN MP-BGP EVPN spine and leaf架构使用多协议边界网关协议以太网虚拟专用网(MP-BGP EVPN)作为VXLAN的控制平面。该技术为VXLAN覆盖网络中的第2层和第3层转发提供了控制平面和数据平面分离以及统一的控制平面。本节介绍Cisco Nexus硬件交换机(如Cisco Nexus 5600平台交换机和Cisco Nexus 7000和9000系列交换机)上的VXLAN MP-BGP EVPN。
架构师研究会
2020/07/20
2.4K0
「数据中心」脊叶网络架构:Cisco VXLAN MP-BGP EVPN脊叶网络
【重识云原生】第四章云网络4.3.10.2节——VXLAN Overlay网络方案设计
        VXLAN 本质上是一种重叠封装技术,它创建了一个覆盖在现有物理网络基础架构之上的虚拟网络。使用underlay IP网络,并在其上构建灵活的二层overlay逻辑网络。通过覆盖,任何第 2 层连接都可以跨越第 3 层网络。
江中散人_Jun
2022/06/12
1.1K0
【重识云原生】第四章云网络4.3.10.2节——VXLAN Overlay网络方案设计
最全 VxLAN 知识详解
VXLAN(Virtual eXtensible Local Area Network,虚拟扩展局域网),是由IETF定义的NVO3(Network Virtualization over Layer 3)标准技术之一,是对传统VLAN协议的一种扩展。VXLAN的特点是将L2的以太帧封装到UDP报文(即L2 over L4)中,并在L3网络中传输。 如图1-1所示,VXLAN本质上是一种隧道技术,在源网络设备与目的网络设备之间的IP网络上,建立一条逻辑隧道,将用户侧报文经过特定的封装后通过这条隧道转发。从用户的角度来看,接入网络的服务器就像是连接到了一个虚拟的二层交换机的不同端口上(可把蓝色虚框表示的数据中心VXLAN网络看成一个二层虚拟交换机),可以方便地通信。
杰哥的IT之旅
2020/11/23
1.7K1
最全 VxLAN 知识详解
「数据中心」网络架构脊页架构:Cisco VXLAN 泛滥学习 脊页网络
VXLAN是众多可用的网络虚拟化覆盖技术之一,它具有许多优点。它是一个工业标准协议,使用底层IP网络。它将第2层分段扩展到第3层基础设施上,以构建第2层覆盖逻辑网络。它将以太网帧封装到IP用户数据协议(UDP)报头中,并使用普通的IP路由和转发机制将封装的数据包通过底层网络传输到远程VXLAN隧道端点(VTEPs)。思科在2014年左右开始支持VXLanFlood,并在思科Nexus5600平台、思科Nexus7000和9000系列等多种思科Nexus交换机上学习spine和leaf技术。本节介绍Cisco VXLAN洪水和学习这些Cisco硬件交换机的特性。
架构师研究会
2020/07/20
1.4K0
「数据中心」网络架构脊页架构:Cisco VXLAN 泛滥学习 脊页网络
高质量的讲解VXLAN技术
由三个公司创建:Cisco、Arista 和 VMware,VXLAN RFC7348
网络技术联盟站
2023/03/13
6610
高质量的讲解VXLAN技术
「数据中心」数据中心脊页架构:数据中心结构管理、自动化和总结
建立数据中心没有单一的方法。同样,没有单一的方法来管理数据中心结构。Cisco、第三方和开源社区提供了许多不同的工具,可用于监视、管理、自动化和排除数据中心结构的故障。
架构师研究会
2020/07/20
1.2K0
「数据中心」数据中心脊页架构:数据中心结构管理、自动化和总结
为什么说 EVPN 并非一种协议?
EVPN 并非一种协议,而是一种在Overlay网络中利用多协议边界网关协议 (MP-BGP) 作为控制平面的解决方案。此外,EVPN 还采用虚拟可扩展局域网 (VXLAN) 封装作为Overlay网络的数据平面。
通往ICT之路
2024/08/19
2270
为什么说 EVPN 并非一种协议?
什么是 VXLAN?必看!
假设我们有一个物理 LAN,其中网络中有多个具有 IP 的主机10.1.2.0/24,每个主机都可以单独使用交换机与其他主机通话,现在,我们要对一组主机进行分组并将它们彼此分开,我们有哪些选择?
网络技术联盟站
2021/11/01
1.1K0
什么是 VXLAN?必看!
网络工程师:VXLAN这9个术语要精通!
VXLAN(Virtual Extensible LAN)是一种用于在大规模数据中心中扩展二层网络的隧道技术。它通过在现有的三层网络基础设施上创建虚拟的二层网络,使不同物理位置的虚拟机能够互相通信。本文将详细介绍VXLAN中的一些关键术语,包括租户、Underlay网络和Overlay网络、NVE、VTEP、VNI、BD、VBDIF接口、VAP和网关。
网络技术联盟站
2025/01/14
2580
网络工程师:VXLAN这9个术语要精通!
理解Neutron(3):Neutron Open vSwitch + GRE/VxLAN 虚拟网络
特别说明:本文于2015年基于OpenStack M版本发表于本人博客,现转发到公众号。因为时间关系,本文部分内容可能已过时甚至不正确,请读者注意。
SammyLiu
2019/06/28
2K0
理解Neutron(3):Neutron Open vSwitch + GRE/VxLAN 虚拟网络
传统数据中心 VS Spine-Leaf 结构
为了满足现代网络的需求,数据中心网络必须优先考虑最核心的功能,例如强大的网络带宽、高可用性、可扩展性和安全等。
通往ICT之路
2024/04/17
4920
传统数据中心 VS Spine-Leaf 结构
VXLAN篇之进阶
首先需要指出的是,IRB有两种:非对称IRB(Asymmetric Integrated Routing and Bridging),对称IRB(Symmetric Integrated Routing and Bridging)。
SDNLAB
2019/09/09
2.6K0
一文读懂EVPN技术
最初的VXLAN方案(RFC7348)中没有定义控制平面,VXLAN隧道需要手工配置,然后通过流量泛洪的方式进行主机地址的学习。这种方式实现上较为简单,但是会导致网络中存在很多泛洪流量、网络扩展困难。
SDNLAB
2022/12/14
4.4K0
一文读懂EVPN技术
深入浅出云计算VPC网络之VXLAN
云计算三大组成部分:计算、存储和网络。VXLAN属于云计算虚拟化网络的非常重要的一部分,现在大多数云计算虚拟化网络都是基于此协议实现数据中心互联和虚拟机迁移 ,在数量级很大的虚拟机上完成这些工作是一个非常大的挑战。主要面临以下挑战:
吕海峰
2020/06/18
8.2K0
深入浅出云计算VPC网络之VXLAN
【重识云原生】第四章云网络4.3.10节——VXLAN技术
        VXLAN (Virtual eXtensible LAN,可扩展虚拟局域网络) 是一种Internet 标准重叠网络虚拟化技术,它提供了一种在 IP(第 3 层)网络上封装以太网(第 2 层)帧的方法,这一概念通常被称为“隧道”。VXLAN采用MAC in UDP(User Datagram Protocol)封装方式,是NVO3(Network Virtualization over Layer 3)中的一种网络虚拟化技术。
江中散人_Jun
2022/06/12
1.4K0
【重识云原生】第四章云网络4.3.10节——VXLAN技术
什么是 VxLAN?
VxLAN 全称是 Visual eXtensible Local Area Network(虚拟扩展本地局域网),从名字上就知道,这是一个 VLAN 的扩展协议。
Linux云计算网络
2019/07/08
9.2K3
VXLAN篇之Multi-Pod
之前的《VXLAN篇之进阶》说到了multi-pod,multi-fabric,multi-site。这次,再把multi-pod给填上!
SDNLAB
2019/10/22
1.6K0
VXLAN篇之Multi-Pod
VxLAN工作原理
随着虚拟化和云计算的发展,数据中心规模的越来越大,因此虚拟机的数量越来越多。而传统的VLAN ID只有12 bit,导致最大只能有4096个虚拟2层网络;
段立功
2022/06/13
4420
VxLAN工作原理
云原生虚拟网络之 VXLAN 协议
第一次认识 VXLAN 是在看 k8s 里面用到的叫 flannel 的网络插件有个 VXLAN 模式,利用它实现了 Overlay Network(覆盖网络),可以把所有容器连通在一起。所以本篇文章,我们一起来看看 VXLAN 是怎么将不同容器之间的网络进行打通的。
luozhiyun
2023/10/16
6530
云原生虚拟网络之 VXLAN 协议
云计算和虚拟化都要用到的核心技术 VXLAN 网络,你掌握了吗?
云计算、虚拟化相关技术的发展,传统的网络无法满足于规模大、灵活性要求高的云数据中心的要求,于是便有了 overlay 网络的概念。overlay 网络中被广泛应用的就是 vxlan 技术。首先我们了解一下随着云计算的发展,传统网络面临哪些挑战。
iMike
2020/04/21
1.2K0
云计算和虚拟化都要用到的核心技术 VXLAN 网络,你掌握了吗?
相关推荐
「数据中心」脊叶网络架构:Cisco VXLAN MP-BGP EVPN脊叶网络
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验