当前位置: 首页 > news >正文

Spring源码(十二):Spring MVC之Spring Boot

本篇将详细讨论Spring Boot 的启动/加载、处理请求的具体流程。我们先从一个简单的Spring Boot项目日志开始分析(这里假设读者已经仔细阅读完了前面的文章,且对Spring源码有一定深度的了解,否则会看得一脸懵逼)。

本文为2024重置版,基于JDK8、Spring Boot 2.2.6.RELEASE(最初版本基于Spring MVC + XML配置,现已废弃去除)。

一、相关代码

1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><groupId>site.xiaokui</groupId><artifactId>k-2019</artifactId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>k-mini</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>
</project>

2、相关类

@SpringBootApplication
public class MiniAppRunner {public static void main(String[] args) {SpringApplication.run(MiniAppRunner.class, args);}
}
@Slf4j
@RequiredArgsConstructor
@RestController
public class TestController {@PostMapping("/test")@ResponseBodypublic Object test0(@RequestBody Map<String, Object> map) {log.info("前端传来数据:" + map);return map;}
}
POST http://127.0.0.1:7077/test?aa=1&bb=2
Content-Type: application/json{"data": {"login_type": "08","login_str": "abcd"}
}

3、相关配置

debug: trueserver:port: 7077logging:level.root: tracelevel.org.apache.tomcat: infolevel.sun.rmi: info

以上为相关测试代码,读者也可搭建环境自行测试(省略具体输出日志)。

二、SpringApplication

1、构造方法

// main方法入口,来自类 SpringApplication
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class<?>[] { primarySource }, args);
}public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);
}public SpringApplication(Class<?>... primarySources) {this(null, primarySources);
}public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// 判断当前运行环境,可选 none、servlet、reactivethis.webApplicationType = WebApplicationType.deduceFromClasspath();// 读取 META-INF/spring.factories,加载相关启动类// 加载初始化相关类,共有7个 = 5 + 2,数字刚好与下文的两份 spring.factories对上// 注意这里只是设置,还尚未开始调用setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 加载监听器,监听相关事件,共有11个 = 10 + 1setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 寻找main方法所在的类作为主类this.mainApplicationClass = deduceMainApplicationClass();
}

2、spring.factories

来自jar包 org.springframework.boot:spring-boot:2.2.6.REALEASE

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers# Application Context Initializers,5个
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer# Application Listeners,10个
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

来自来自jar包 org.springframework.boot:spring-boot-autoconfigure:2.2.6.REALEASE

# Initializers,2个
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener# Application Listeners,1个
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.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveRestClientAutoConfiguration,\
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.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
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.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
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.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
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、事件周期图

下图展现SpringApplication的事件全生命周期,读者可以按照此图对照源码进行阅读。其中相关核心类有(断点神类)

  • SpringApplication
  • SimpleApplicationEventMulticaster

4、主干

// 主干逻辑
public ConfigurableApplicationContext run(String... args) {// 统计耗时StopWatch stopWatch = new StopWatch();stopWatch.start();// WebApplicationContextConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();// 设置无图形界面服务器工作模式configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);// 触发事件 ApplicationStartingEvent// 分别为 LoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、LiquibaseServiceLocatorApplicationListener// 这里重点关注下 LoggingApplicationListener、BackgroundPreinitializerlisteners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 准备环境,包含各种系统属性、环境变量、配置值// 触发事件 ApplicationEnvironmentPreparedEventConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);// 创建 AnnotationConfigServletWebServerApplicationContextcontext = createApplicationContext();exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);// 触发 applyInitializers// 触发事件 ApplicationContextInitializedEvent、ApplicationPreparedEventprepareContext(context, environment, listeners, applicationArguments, printedBanner);// 完成刷新触发事件 ContextRefreshedEvent、ServletWebServerInitializedEventrefreshContext(context);// 空实现,留作扩展afterRefresh(context, applicationArguments// 完成统计耗时stopWatch.stop();if (this.logStartupInfo) {// 打印启动耗时// Started MiniAppRunner in 106.05 seconds (JVM running for 189.145)new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}// 触发事件 ApplicationStartedEventlisteners.started(context);// 调用 ApplicationRunner、CommandLineRunnercallRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}try {// 发布事件 ApplicationReadyEvent,代表Spring已经完全启动了listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;
}

三、系统属性初始化

1、ApplicationStartingEvent

1、LoggingApplicationListener
// 来自类 LoggingApplicationListener
@Override
public void onApplicationEvent(ApplicationEvent event) {// 系统开始启动事件if (event instanceof ApplicationStartingEvent) {onApplicationStartingEvent((ApplicationStartingEvent) event);}else if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}else if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent((ApplicationPreparedEvent) event);}else if (event instanceof ContextClosedEvent&& ((ContextClosedEvent) event).getApplicationContext().getParent() == null) {onContextClosedEvent();}else if (event instanceof ApplicationFailedEvent) {onApplicationFailedEvent();}
}private void onApplicationStartingEvent(ApplicationStartingEvent event) {// 准备 LoggingSystemthis.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());// 日志系统初始化之前的准备工作this.loggingSystem.beforeInitialize();
}// 来自类 LoggingSystem
@Override
public void beforeInitialize() {LoggerContext loggerContext = getLoggerContext();if (isAlreadyInitialized(loggerContext)) {return;}// 会触发父类 Slf4JLoggingSystem 的初始化// 此步骤会尽量保证系统只有一个日志框架生效,例如jdklog、logback、log4j只会生效一个super.beforeInitialize();loggerContext.getTurboFilterList().add(FILTER);
}
2、BackgroundPreinitializer
// 来自类 BackgroundPreinitializer
@Override
public void onApplicationEvent(SpringApplicationEvent event) {if (!Boolean.getBoolean(IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME)&& event instanceof ApplicationStartingEvent && multipleProcessors()&& preinitializationStarted.compareAndSet(false, true)) {performPreinitialization();}if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent)&& preinitializationStarted.get()) {try {preinitializationComplete.await();}catch (InterruptedException ex) {Thread.currentThread().interrupt();}}
}// 主要作用是执行类的预热,因为组件较多,提前异步实例化,可提升系统启动速度
// 实例化好的对象,最终会保存到一个静态对象中,下次直接使用即可
private void performPreinitialization() {try {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {runSafely(new ConversionServiceInitializer());runSafely(new ValidationInitializer());runSafely(new MessageConverterInitializer());runSafely(new JacksonInitializer());runSafely(new CharsetInitializer());preinitializationComplete.countDown();}public void runSafely(Runnable runnable) {try {runnable.run();}catch (Throwable ex) {// Ignore}}}, "background-preinit");thread.start();}catch (Exception ex) {// This will fail on GAE where creating threads is prohibited. We can safely// continue but startup will be slightly slower as the initialization will now// happen on the main thread.preinitializationComplete.countDown();}
}

2、prepareEnvironment

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environment// 此时具有环境变量和系统属性,但还未有配置文件属性ConfigurableEnvironment environment = getOrCreateEnvironment();configureEnvironment(environment, applicationArguments.getSourceArgs());ConfigurationPropertySources.attach(environment);// 发布环境就绪事件// 会触发监听类 ConfigFileApplicationListener、AnsiOutputApplicationListener、LoggingApplicationListener// ClasspathLoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、FileEncodingApplicationListenerlisteners.environmentPrepared(environment);bindToSpringApplication(environment);if (!this.isCustomEnvironment) {environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,deduceEnvironmentClass());}ConfigurationPropertySources.attach(environment);return environment;
}
1、getOrCreateEnvironment
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();}
}public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {}// 会首先触发父类的初始化
public AbstractEnvironment() {// 开始读取配置customizePropertySources(this.propertySources);
}// 来自类 StandardServletEnvironment
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));}// 回调父类 customizePropertySourcessuper.customizePropertySources(propertySources);
}// 来自类 StandardEnvironment
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {// 底层为 (Map) System.getProperties()propertySources.addLast(new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));// 底层为 (Map) System.getenv()propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
2、ApplicationEnvironmentPreparedEvent

限于篇幅,这里不详细展开,大概列下:

  • ConfigFileApplicationListener:用于加载外部配置文件。
  • AnsiOutputApplicationListener:让你的终端(可以是控制台、可以是日志文件)支持Ansi彩色输出。
  • LoggingApplicationListener:初始化日志系统。
  • ClasspathLoggingApplicationListener:用于把classpath路径以log.debug()输出。
  • BackgroundPreinitializer:无动作。
  • DelegatingApplicationListener:执行通过外部化配置context.listener.classes = xxx,xxx的监听器们,然后把该事件广播给他们。
  • FileEncodingApplicationListener:检查文件编码file.encoding。

ConfigFileApplicationListener 部分关键代码如下

// 来自类 ConfigFileApplicationListener
@Override
public void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent(event);}
}private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {// 分别为 SystemEnvironmentPropertySourceEnvironmentPostProcessor、SpringApplicationJsonEnvironmentPostProcessor// CloudFoundryVcapEnvironmentPostProcessor、DebugAgentEnvironmentPostProcessorList<EnvironmentPostProcessor> postProcessors = loadPostProcessors();// 注意 add this了// 读取外部配置,这个最重要的活是自己来干postProcessors.add(this);AnnotationAwareOrderComparator.sort(postProcessors);for (EnvironmentPostProcessor postProcessor : postProcessors) {postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication());}
}// 来自类 ConfigFileApplicationListener
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {addPropertySources(environment, application.getResourceLoader());
}// 鉴于代码较多,这里只列举部分关键代码
// 默认配置文件路径 DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {getSearchLocations().forEach((location) -> {boolean isFolder = location.endsWith("/");Set<String> names = isFolder ? getSearchNames() : NO_SEARCH_NAMES;names.forEach((name) -> load(location, name, profile, filterFactory, consumer));});
}

LoggingApplicationListener 部分关键代码如下

// 来自类 LoggingApplicationListener
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {// 上一事件已经完成准备工作if (this.loggingSystem == null) {this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());}// 直接跳到这里开始初始化initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader());
}protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {// 设置日志属性默认值new LoggingSystemProperties(environment).apply();// 日志文件名 logging.file.name、logging.file// 日志文件路径 logging.file.path、logging.paththis.logFile = LogFile.get(environment);if (this.logFile != null) {this.logFile.applyToSystemProperties();}// 默认logger web & sqlthis.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);// 设置early日志级别,主要是 debug/trace = true/falseinitializeEarlyLoggingLevel(environment);// 根据日志配置,初始化日志系统,包括 日志输出格式、日志存放路径、日志存放策略等initializeSystem(environment, this.loggingSystem, this.logFile);// 设置日志级别,含root和各个子包路径initializeFinalLoggingLevels(environment, this.loggingSystem);// 注册销毁钩子registerShutdownHookIfNecessary(environment, this.loggingSystem);
}

3、printBanner

打印banner,关键类为 SpringApplicationBannerPrinter,这里不做详细展开。

// 只列举部分字段
class SpringApplicationBannerPrinter {static final String BANNER_LOCATION_PROPERTY = "spring.banner.location";static final String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";static final String DEFAULT_BANNER_LOCATION = "banner.txt";static final String[] IMAGE_EXTENSION = { "gif", "jpg", "png" };// 默认打印 spring boot 版本信息private static final Banner DEFAULT_BANNER = new SpringBootBanner();private final ResourceLoader resourceLoader;private final Banner fallbackBanner;// 其他略
}

四、WebApplication初始化

1、createApplicationContext

// 来自类 SpringApplication
protected ConfigurableApplicationContext createApplicationContext() {Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {try {switch (this.webApplicationType) {case SERVLET:// 走此逻辑,类为 AnnotationConfigServletWebServerApplicationContextcontextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);break;case REACTIVE:// AnnotationConfigReactiveWebServerApplicationContextcontextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);break;default:// AnnotationConfigApplicationContext     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);
}

2、prepareContext

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {context.setEnvironment(environment);postProcessApplicationContext(context);// 触发初始化逻辑,共7个,具体参见前文applyInitializers(context);// 发布事件 ApplicationContextInitializedEventlisteners.contextPrepared(context);if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beansConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}if (this.lazyInitialization) {context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}// Load the sourcesSet<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");load(context, sources.toArray(new Object[0]));// 发布 ApplicationPreparedEventlisteners.contextLoaded(context);
}
1、applyInitializers
// 触发相关类为 DelegatingApplicationContextInitializer、SharedMetadataReaderFactoryContextInitializer、ContextIdApplicationContextInitializer
// ConfigurationWarningsApplicationContextInitializer、RSocketPortInfoApplicationContextInitializer
// ServerPortInfoApplicationContextInitializer、ConditionEvaluationReportLoggingListener
protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),ApplicationContextInitializer.class);Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");initializer.initialize(context);}
}
2、contextPrepared
// 来自类 SpringApplicationRunListeners
// 发布WebApplication就绪事件
void contextPrepared(ConfigurableApplicationContext context) {for (SpringApplicationRunListener listener : this.listeners) {listener.contextPrepared(context);}
}// 来自类 EventPublishingRunListener
@Override
public void contextPrepared(ConfigurableApplicationContext context) {this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}	
3、contextLoaded
// 来自类 SpringApplicationRunListeners
// 发布WebApplication加载完毕事件
void contextLoaded(ConfigurableApplicationContext context) {for (SpringApplicationRunListener listener : this.listeners) {listener.contextLoaded(context);}
}// 来自类 EventPublishingRunListener
@Override
public void contextLoaded(ConfigurableApplicationContext context) {for (ApplicationListener<?> listener : this.application.getListeners()) {if (listener instanceof ApplicationContextAware) {((ApplicationContextAware) listener).setApplicationContext(context);}context.addApplicationListener(listener);}this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}	

3、refreshContext

// 来自类 SpringApplication
private void refreshContext(ConfigurableApplicationContext context) {refresh(context);if (this.registerShutdownHook) {try {context.registerShutdownHook();}catch (AccessControlException ex) {// Not allowed in some environments.}}
}protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);// 触发上下文的刷新动作// 这里不做过多展开,具体请参见前文((AbstractApplicationContext) applicationContext).refresh();
}public Collection<ApplicationListener<?>> getApplicationListeners() {return this.applicationListeners;
}// 来自类 AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.// 发布 ContextRefreshedEvent、ServletWebServerInitializedEvent 事件// 会有一次 super.finishRefreshfinishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}
}

刷新完后的 AnnotationConfigServletWebServerApplicationContext 将完全具有 BeanFactoryApplicationContext 的功能,剩下的就是一些收尾工作。

在完成刷新之后,会发布 ContextRefreshedEventServletWebServerInitializedEvent 事件。

4、callRunners

我们可以在Spring完全启动后,通过实现 ApplicationRunnerCommandLineRunner 接口做一些事情。

private void callRunners(ApplicationContext context, ApplicationArguments args) {List<Object> runners = new ArrayList<>();runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());AnnotationAwareOrderComparator.sort(runners);for (Object runner : new LinkedHashSet<>(runners)) {if (runner instanceof ApplicationRunner) {callRunner((ApplicationRunner) runner, args);}if (runner instanceof CommandLineRunner) {callRunner((CommandLineRunner) runner, args);}}
}

再最后就是发布 ApplicationReadyEvent,代表Spring已经完全启动了。

至此,Spring Boot相关源码已梳理完毕,下篇将着重分析Spring是如何处理一个请求的。

相关文章:

Spring源码(十二):Spring MVC之Spring Boot

本篇将详细讨论Spring Boot 的启动/加载、处理请求的具体流程。我们先从一个简单的Spring Boot项目日志开始分析&#xff08;这里假设读者已经仔细阅读完了前面的文章&#xff0c;且对Spring源码有一定深度的了解&#xff0c;否则会看得一脸懵逼&#xff09;。 本文为2024重置…...

Kafka 之事务消息

前言&#xff1a; 在分布式消息系统中&#xff0c;事务消息也是一个热门课题&#xff0c;在项目的实际业务场景中&#xff0c;如果用到事务消息的场景也不少见&#xff0c;那 Kafka 作为一个高性能的分布式消息中间件&#xff0c;同样也支持事务消息&#xff0c;本篇我们将对 …...

小菜家教平台(四):基于SpringBoot+Vue打造一站式学习管理系统

前言 昨天配置完了过滤器&#xff0c;权限检验&#xff0c;基本的SpringSecurity功能已经配置的差不多了&#xff0c;今天继续开发&#xff0c;明天可能会暂停一天整理一下需求&#xff0c;然后就进行CRUD了。 今日进度 补充SpringSecurity异常处理和全局异常处理器 详细操作…...

解决 Vue3、Vite 和 TypeScript 开发环境下跨域的问题,实现前后端数据传递

引言 本文介绍如何在开发环境下解决 Vite 前端&#xff08;端口 3000&#xff09;和后端&#xff08;端口 80&#xff09;之间的跨域问题&#xff1a; 在开发环境中&#xff0c;前端使用的 Vite 端口与后端端口不一致&#xff0c;会产生跨域错误提示&#xff1a; Access to X…...

量化交易系统开发-实时行情自动化交易-3.3.数据采集流程

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来说说数据采集流程&#xff0c;后…...

探索PyAV:Python中的多媒体处理利器

文章目录 探索PyAV&#xff1a;Python中的多媒体处理利器第一部分&#xff1a;背景介绍第二部分&#xff1a;PyAV是什么&#xff1f;第三部分&#xff1a;如何安装PyAV&#xff1f;第四部分&#xff1a;简单的库函数使用方法1. 打开文件2. 查看流3. 遍历帧4. 编码帧5. 关闭输出…...

SpringBoot源码解析(三):启动开始阶段

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 目录 前言一、入口二、SpringApplicationRunListener1、作用…...

C# const与readonly关键字的区别

在C#中&#xff0c;readonly关键字用于定义在对象创建后不能更改的字段。它可以与常量(const)有些相似&#xff0c;但也有显著不同。以下是readonly关键字的一些关键点&#xff1a; 定义与用法&#xff1a; readonly字段可以在类的构造函数中初始化&#xff0c;而const字段必须…...

【数据分享】1901-2023年我国省市县镇四级的逐年降水数据(免费获取/Shp/Excel格式)

之前我们分享过1901-2023年1km分辨率逐月降水栅格数据和Shp和Excel格式的省市县四级逐月降水数据&#xff0c;原始的逐月降水栅格数据来源于彭守璋学者在国家青藏高原科学数据中心平台上分享的数据&#xff01;基于逐月数据我们采用求年累计值的方法得到逐年降水栅格数据&#…...

hhdb数据库介绍(9-4)

访问安全 权限体系 计算节点有两类用户&#xff0c;一类是计算节点数据库用户&#xff0c;用于操作数据&#xff0c;执行SELECT&#xff0c;UPDATE&#xff0c;DELETE&#xff0c;INSERT等SQL语句。另一类是关系集群数据库可视化管理平台用户&#xff0c;用于管理配置信息。此…...

苍穹外卖的分层所用到的技术以及工具+jwt令牌流程图(jwt验证)

分层用到的技术以及工具: jwt令牌流程图:...

Python——数列1/2,2/3,3/4,···,n/(n+1)···的一般项为Xn=n/(n+1),当n—>∞时,判断数列{Xn}是否收敛

没注释的源代码 from sympy import * n symbols(n) s n/(n1) print(数列的极限为&#xff1a;,limit(s,n,oo))...

css:还是语法

emmet的使用 emmet是一个插件&#xff0c;Emmet 是 Zen Coding 的升级版&#xff0c;由 Zen Coding 的原作者进行开发&#xff0c;可以快速的编写 HTML、CSS 以及实现其他的功能。很多文本编辑器都支持&#xff0c;我们只是学会使用它&#xff1a; 生成html结构 <!-- emme…...

关于 el-table 的合计行问题

目录 一.自定义合计行 二.合计行不展示&#xff0c;只有缩放/变大窗口或者F12弹出后台时才展示 三.合计行出现了表格滚动条下方 四.合计行整体样式的修改 五.合计行单元格样式修改 1.css 2.jsx方式 六.合计行单元格合并 一.自定义合计行 通过 show-summary 属性开启合计…...

解决SVN更新,提交错误乱码

执行清理操作&#xff0c;没有菜单的情况 1.点击TortoiseSVN-设置-如图勾选 注意&#xff1a;下图没有点击上下文菜单勾选清理 选择对应文件目录&#xff0c;执行【清理】操作 2.如果还是乱码&#xff0c;如上操作勾选解除文件锁定&#xff0c; 执行【破除锁定】后再次执行【…...

《Python网络安全项目实战》项目4 编写网络扫描程序

《Python网络安全项目实战》项目4 编写网络扫描程序 项目4 编写网络扫描程序任务4.1 扫描内网有效IP地址任务描述任务分析任务实施任务拓展 任务4.2 编写端口扫描工具任务描述任务分析任务实施相关知识任务评价任务拓展项目评价 项目4 编写网络扫描程序 许多扫描工具是由Pytho…...

Python金融大数据分析概述

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【海拥导航】&#x1f485; 想寻找共同学习交流&#xff0c;摸鱼划水的小伙伴&#xff0c;请点击【全栈技术交流群】 金融大数据分析在金融科技领域越来越重要&#xff0c;它涉及从海量数据中提取洞察&#xff0c;为金…...

黑马产品经理

1、合格的产品经理 什么是产品&#xff1f; 什么是产品经理&#xff1f; 想清楚产品怎么做的人。 合格的产品经理 2、产品经理的分类 为什么会有不同的分类&#xff1f; 按服务对象划分 按产品平台划分 公司所属行业不同&#xff08;不限于以下&#xff09; 工作内容划分 …...

机器学习——损失函数、代价函数、KL散度

&#x1f33a;历史文章列表&#x1f33a; 机器学习——损失函数、代价函数、KL散度机器学习——特征工程、正则化、强化学习机器学习——常见算法汇总机器学习——感知机、MLP、SVM机器学习——KNN机器学习——贝叶斯机器学习——决策树机器学习——随机森林、Bagging、Boostin…...

首次超越扩散模型和非自回归Transformer模型!字节开源RAR:自回归生成最新SOTA!

文章链接&#xff1a;https://arxiv.org/pdf/2411.00776 项目链接&#xff1a;https://yucornetto.github.io/projects/rar.html 代码&模型链接&#xff1a;https://github.com/bytedance/1d-tokenizer 亮点直击 RAR&#xff08;随机排列自回归训练策略&#xff09;&#x…...

C语言最简单的扫雷实现(解析加原码)

头文件 #define ROW 9 #define COL 9 #define ROWS ROW2 #define COLS COL2 #include <stdio.h> #include <stdlib.h> #include <time.h> #define numlei 10do while可以循环玩 两个板子&#xff0c;内板子放0&#xff0c;外板子放* set函数初始化两个板子 …...

20. 类模板

一、什么是类模板 类模板用于建立一个通用类&#xff0c;类中的成员数据类型可以不具体指定&#xff0c;用一个虚拟的类型来代替。它的语法格式如下&#xff1a; template<typename T>类模板与函数模板相比主要有两点区别&#xff1a;1) 类模板没有自动类型推导的方式。…...

SSL证书以及实现HTTP反向代理

注意&#xff1a; 本文内容于 2024-11-09 19:20:07 创建&#xff0c;可能不会在此平台上进行更新。如果您希望查看最新版本或更多相关内容&#xff0c;请访问原文地址&#xff1a;SSL证书以及实现HTTP反向代理。感谢您的关注与支持&#xff01; 之前写的HTTP反向代理工具&…...

多种算法解决组合优化问题平台

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月11日7点12分 点击开启你的论文编程之旅https://www.aspiringcode.com/content?id17302099790265&uidef7618fa204346ff9…...

【笔记】LLC电路工作频点选择 2-1 输出稳定性的限制

LLC工作模式的分析参考了&#xff1a;现代电力电子学&#xff0c;电力出版社&#xff0c;李永东 1.LLC电路可以选择VCS也可以选择ZVS 1.1选择ZCS时&#xff0c;开关管与谐振电感串联后&#xff0c;与谐振电容并联&#xff1a; 1.2选择ZVS时&#xff0c;开关管仅仅安装在谐振电…...

Linux系统程序设计--2. 文件I/O

文件I/O 标准C的I/O FILE结构体 下面只列出了5个成员 可以观察到&#xff0c;有些函数没有FILE类型的结构体指针例如printf主要是一些标准输出&#xff0c;因为其内部用到了stdin&#xff0c;stdout&#xff0c;stderr查找文件所在的位置:find \ -name stat.h查找头文件所…...

右值引用——C++11新特性(一)

目录 一、右值引用与移动语义 1.左值引用与右值引用 2.移动构造和移动赋值 二、引用折叠 三、完美转发 一、右值引用与移动语义 1.左值引用与右值引用 左值&#xff1a;可以取到地址的值&#xff0c;比如一些变量名&#xff0c;指针等。右值&#xff1a;不能取到地址的值…...

JavaScript 观察者设计模式

观察者模式:观察者模式&#xff08;Observer mode&#xff09;指的是函数自动观察数据对象&#xff0c;一旦对象有变化&#xff0c;函数就会自动执行。而js中最常见的观察者模式就是事件触发机制。 ES5/ES6实现观察者模式(自定义事件) - 简书 先搭架子 要有一个对象&#xff…...

鸿蒙进阶篇-网格布局 Grid/GridItem(二)

hello大家好&#xff0c;这里是鸿蒙开天组&#xff0c;今天让我们来继续学习鸿蒙进阶篇-网格布局 Grid/GridItem&#xff0c;上一篇博文我们已经学习了固定行列、合并行列和设置滚动&#xff0c;这一篇我们将继续学习Grid的用法&#xff0c;实现翻页滚动、自定义滚动条样式&…...

数据仓库之 Atlas 血缘分析:揭示数据流奥秘

Atlas血缘分析在数据仓库中的实战案例 在数据仓库领域&#xff0c;数据血缘分析是一个重要的环节。血缘分析通过确定数据源之间的关系&#xff0c;以及数据在处理过程中的变化&#xff0c;帮助我们更好地理解数据生成的过程&#xff0c;提高数据的可靠性和准确性。在这篇文章中…...

珠海建设工程交易中心/网络seo公司

系列文章 操作系统权限维持&#xff08;一&#xff09;之Windows系统-粘贴键后门 操作系统权限维持&#xff08;二&#xff09;之Windows系统-克隆账号维持后门 操作系统权限维持&#xff08;三&#xff09;之Windows系统-启动项维持后门 操作系统权限维持&#xff08;四&…...

php网站建设流程/学seo如何入门

前段时间的帖子&#xff0c;利用TPYBoard v102做的DIY照相机&#xff0c;周末实物终于做出来了&#xff0c;加了两个按键模块和一个5110&#xff0c;做的有点糙啊----望大家勿怪&#xff0c;哈哈哈。拍出来图片还算清晰&#xff0c;串口摄像头模块用的30w像素的&#xff08;贫穷…...

wordpress更新主题报错/聊城seo

hello&#xff0c;大家好&#xff0c;我是小楼。 今天给大家分享一个关于HBase数据倾斜的排查案例&#xff0c;不懂调用链&#xff1f;不懂HBase&#xff1f;没关系&#xff0c;看完包懂~ 背景 最近HBase负责人反馈HBase存储的调用链数据偶尔出现极其严重的倾斜情况&#xf…...

合肥做网站公司/网站优化的方法与技巧

解析器就是服务端写api,对于前端用户发来的数据进行解析。解析完之后拿到自己能用数据。 本质就是对请求体中的数据进行解析。 django的解析器 post请求过来之后&#xff0c;django 的request.body一定有值&#xff0c;request.post不一定有值。如果想让request.post有值&#…...

做二手车网站需要什么/深圳网站营销seo电话

位图像素的颜色 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 0 Accepted Submission(s): 0Problem Description有一个在位图上画出矩形程序&#xff0c;一开始位图都被初始化为白色&#xff08;RGB颜色表示…...

aide web/企业排名优化公司

C语言的精髓——指针详解 C 语言的精髓语言的精髓————指针详解指针详解 朱有鹏 1.2、指针变量的类型作用、指针变量的类型作用 对于普通变量的来说&#xff0c;其类型的作用主要有这么几个方面: (1)程序员写代码时识别用&#xff1a;不涉及强制转换时&#xff0c;知道该变量…...