一、前沿

Spring Boot 是 Spring 的衍生产品,是基于Spring4的条件注册的一套快速开发整合包,它实现了自动配置降低了项目搭建的复杂度。但是Spring Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序,是用于提升Spring开发者体验的工具

Spring Boot 集成了大量常用的第三方库配置(例如Jackson、JDBC、Mongo、Redis、MQ、Mail等等),Spring Boot应用中这些第三方库几乎可以做到零配置的开箱即用(out-of-the-box),大部分的Spring Boot应用都只需要非常少量的配置代码即可,开发者能够更加专注于业务逻辑。

Spring Boot 集成了 tomcat 和 jetty WEB 服务器,Spring Boot 默认使用 tomcat 做 WEB 服务器,如果你使用的是 tomcat,则不需要单独配置 tocmat 了

Spring Boot 和 Spring 的区别

1)、Spring Boot 实现了自动配置,例如 Mybatis、Redis、JDBC、MQ、Mongo等

2)、Spring Boot 集成了 WEB 服务器,例如 Tomcat 和 Jetty

3)、Spring Boot 实现了配置文件的环境隔离,通过 spring.profiles.active 属性可以指定加载某个环境的下的配置文件

接下来我们探究一下 Spring Boot 的启动流程

二、启动流程图

Spring Boot 启动流程图如下:

详细的流程图如下:

从上图中可知,Spring Boot 启动共分为三个部分

1)、SpringApplication 的初始化模块,即配置了 source、web环境、初始化构造器、应用监听器和main方法所在类

2)、SpringApplication 的启动模块,即启动了流程的监听器、加载环境配置和创建上下文 ApplicationContext

3)、Spring Boot 的自动化配置模块,即调用 ApplicationContext 的 refresh 方法刷新上下文,完成了所有非lazy的Singleton Bean 的加载,其中包括最核心的 Spring Boot 的各种自动化配置类的加载

下面从源码角度分别对这三个部分展开详细分析

3.1 初始化模块

Spring Boot 的入口在带有 @SpringBootApplication 注解的 main 方法中,在 main 方法中主要做了两件事

1)、构造 SpringApplication,即 new SpringApplication(),进行初始化模块操作

2)、调用 SpringApplication 的 run 方法完成 Spring Boot 的启动

代码如下:

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.env.ConfigurableEnvironment;/*** springBoot主入口** @create 2019-12-31 11:36**/
@SpringBootApplication(scanBasePackages = "com.springboot.demo")
@MapperScan("com.springboot.db.mapper")
@ImportResource("classpath:config/application.xml")
public class MainApplication {public static void main(String[] args) {SpringApplication application = new SpringApplication(MainApplication.class);ConfigurableApplicationContext ctx = application.run(args);}
}

从启动类中可知 @SpringBootApplication 注解很关键,下面看一下其作用,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM,classes = AutoConfigurationExcludeFilter.class) })
@ConfigurationPropertiesScan
public @interface SpringBootApplication {// 排除特定的自动配置类@AliasFor(annotation = EnableAutoConfiguration.class)Class<?>[] exclude() default {};// 排除特定的自动配置类的名称@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};// 扫描 scanBasePackages 配置的包下的组件,比如 @Service、@Component 等// 默认扫描主类所在包下的所有组件@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")String[] scanBasePackages() default {};// 扫描 scanBasePackageClasses 配置的类所在的包组件@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")Class<?>[] scanBasePackageClasses() default {};// 是否代理 bean,默认是 true@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;}

@SpringBootApplication 注解中有包含三个核心注解,分别如下:

@SpringBootConfiguration(内部是 @Configuration 注解) : 这个注解和 @Configuration 注解的作用一样,用来表示被标注的类是一个配置类,会将被标注的类中的所有带 @Bean 注解修饰的方法添加到 Spring 容器中,实例的名称默认是方法名,Spring 会创建出对应的实例 Bean

@EnableAutoConfiguration:开启了 SpringBoot 自动配置,在程序启动时会自动加载 SpringBoot 的自动默认配置,如果有对一些参数进行配置(比如在配置文件中修改了配置属性值),则会在程序启动时或调用时进行追加或者覆盖

@ComponentScan:包扫描注解,默认扫描主类包路径下的组件类,所以最好将启动类 MainApplication 存放在根路径下,这里可以配置自己想要扫描的任何包的路径

@ImportResource:引入某路径下的资源文件

下面看构造 SpringApplication 的具体过程,入口在 SpringApplication 的构造方法,源码如下:

	// 1、 SpringApplication 的构造方法public SpringApplication(Class<?>... primarySources) {this(null, primarySources);}// 2、 SpringApplication 的构造方法@SuppressWarnings({ "unchecked", "rawtypes" })public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {// 配置resourcethis.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// 配置是否是web环境,web环境的话后续需要启动web服务器,比如 tomcatthis.webApplicationType = WebApplicationType.deduceFromClasspath();// 创建初始化构造器,加载所有 MATE-INF/spring.factories 文件中的配置,所有配置缓存到 cache 对象中// 根据 ApplicationContextInitializer 类型从 cache 中获取所有的初始化器,通过反射创建所有初始化器实例setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 根据 ApplicationListener 类型从 cache 中获取所有的应用监听器,通过反射创建所有应用监听器实例setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 设置应用main方法所在的主类this.mainApplicationClass = deduceMainApplicationClass();}// 3、SpringApplication 的 getSpringFactoriesInstances 方法private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {// 从 MATE-INF/Spring.factories 文件中加载指定 type 类型的 Beanreturn getSpringFactoriesInstances(type, new Class<?>[] {});}// 4、SpringApplication 的 getSpringFactoriesInstances 方法private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) {// 默认是当前线程上下文的 ClassLoader,resourceLoader 可以指定 ClassLoaderClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicates// SpringFactoriesLoader 加载所有 MATE-INF/Spring.factories 文件中的配置Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 反射创建指定 Type 类型的所有 BeanList<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}

MATE-INF/Spring.factories 文件中的配置内容如下:

上述代码逻辑相对简单,代码注释已经讲得非常清楚了,这里不在做过多赘述了

3.2 启动模块

Spring Boot 的启动从 SpringApplication 的 run 方法开始,源码如下:

 

	// SpringApplication 的 run 方法public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();// 构建 StopWatch,记录启动时间stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();// 配置 Headless ,默认是 trueconfigureHeadlessProperty();// 通过读取缓存 cache 创建 SpringApplicationRunListener 实例SpringApplicationRunListeners listeners = getRunListeners(args);// 启动流程的监听器,即发布 ApplicationStartingEvent 事件listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 准备环境 ConfigurableEnvironment,即配置环境ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);// 配置 spring.beaninfo.ignore 属性值,默认是 trueconfigureIgnoreBeanInfo(environment);// 配置 Banner,这里可以自定义 Spring Boot 启动时输出的 banner 信息Banner printedBanner = printBanner(environment);// 创建 ApplicationContext 上下文,默认是 AnnotationConfigApplicationContextcontext = createApplicationContext();// 创建 SpringBootExceptionReporter 实例exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);// 准备上下文,即配置上下文prepareContext(context, environment, listeners, applicationArguments,printedBanner);// 刷新上下文,加载所有非lazy的Singleton Bean,Spring Boot 的自动配置就是在这里完成的refreshContext(context);// 刷新上下文后的操作,这里是空实现,可以作为扩展afterRefresh(context, applicationArguments);// 记录总启动时间stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}// 发布 ApplicationStartedEvent 事件listeners.started(context);// 调用命令的回调方法callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}try {// 发布 ApplicationReadyEvent 事件listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;}

run 方法中主要实现了以下逻辑:

1)、准备环境 ConfigurableEnvironment,即配置环境

2)、创建 ApplicationContext 上下文

3)、准备上下文,即配置上下文

4)、刷新上下文,加载所有非lazy的Singleton Bean,Spring Boot 的自动配置就是在这里完成的

下面着重分析前三步骤,因为第四个步骤在自动配置模块讲解

3.2.1 配置环境 ConfigurableEnvironment

配置环境入口在 SpringApplication 的 prepareEnvironment 方法,源码如下:

	// 1、SpringApplication 的 prepareEnvironment 方法private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environment// 创建配置环境,默认是 StandardEnvironment,ConfigurableEnvironment environment = getOrCreateEnvironment();// 设置环境配置,即设置 ConversionService、PropertySources 和 Profiles(spring.profiles.active 指定的环境文件)configureEnvironment(environment, applicationArguments.getSourceArgs());// 发布 ApplicationEnvironmentPreparedEvent 事件listeners.environmentPrepared(environment);// 绑定环境到 SpringApplication 应用上bindToSpringApplication(environment);if (!this.isCustomEnvironment) {// 非自定义环境时,使用环境转换器转换环境environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());}// PropertySource 设置 SpringConfigurationPropertySourcesConfigurationPropertySources.attach(environment);return environment;}// 2、SpringApplication 的 getOrCreateEnvironment 方法private ConfigurableEnvironment getOrCreateEnvironment() {if (this.environment != null) {return this.environment;}// 根据 webApplicationType 配置决定环境对象,默认是 StandardEnvironmentswitch (this.webApplicationType) {case SERVLET:return new StandardServletEnvironment();case REACTIVE:return new StandardReactiveWebEnvironment();default:return new StandardEnvironment();}}

在加载配置环境的过程中会判断是否是 web 容器启动,如果是容器启动会加载 StandardServletEnvironment,其继承了 ConfigurableEnvironment,结构图如下:

从上图可以看出,xxxEnvironment 最终都实现了PropertyResolver 接口,而 PropertyResolver 接口是用于解析任何基础源的属性的接口

我们平时通过 Environment 对象获取配置文件中指定 Key 对应的 value 时,就是调用了 PropertyResolver 接口的 getProperty 方法

3.2.2 创建上下文 ApplicationContext

创建上下文 ApplicationContext 入口在 SpringApplication 的 createApplicationContext 方法,源码如下:

	// SpringApplication 的 createApplicationContext 方法protected ConfigurableApplicationContext createApplicationContext() {Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {try {// 根据 webApplicationType 决定实例上下文对象,默认是 AnnotationConfigApplicationContextswitch (this.webApplicationType) {case SERVLET:// web 环境对应的是 AnnotationConfigServletWebServerApplicationContext 上下文contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);break;case REACTIVE:contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);break;default:contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);}}catch (ClassNotFoundException ex) {throw new IllegalStateException("Unable create a default ApplicationContext, "+ "please specify an ApplicationContextClass",ex);}}// 使用构造反射法创建 ApplicationContext 实例return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);}

3.2.3  配置上下文

配置上下文入口在 SpringApplication 的 prepareContext 方法,源码如下:

	// SpringApplication 的 prepareContext 方法private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {// 上下文配置环境context.setEnvironment(environment);// BeanFactory 设置 beanNameGenerator 和 ConversionService,context 设置 ResourceLoader 或者 ClassLoaderpostProcessApplicationContext(context);// 调用所有 ApplicationContextInitializer 的 initialize 方法applyInitializers(context);// 发布 ApplicationContextInitializedEvent 事件listeners.contextPrepared(context);if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beans// 获取 BeanFactory 并注册 ApplicationArguments、Banner等ConfigurableListableBeanFactory 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");// 加载所有source下的所有 Bean 定义 BeanDefinitionload(context, sources.toArray(new Object[0]));// 实现了 ApplicationContextAware 的设置 ApplicationContext,并发布 ApplicationPreparedEvent 事件listeners.contextLoaded(context);}

配置上下文主要实现了以下逻辑:

1)、上下文配置环境

2)、BeanFactory 的一些常规属性设置

3)、调用所有初始化器 ApplicationContextInitializer 的 initialize 方法

4)、加载所有source下的所有 Bean 定义 BeanDefinition,即配置文件中的所有bean配置都转化为 BeanDefinition

5)、设置 ApplicationContext,并发布 ApplicationPreparedEvent 事件

3.3  自动化配置模块

Spring Boot 完成了创建上下文 ApplicationContext 和 配置上下文之后,接下来的工作就是刷新上下文了,Spring Boot 的刷新上下文除了兼具Spring所有功能之外,主要完成了以下工作:

1)、创建了web服务器

2)、加载所有非lazy的Singleton Bean

3)、加载自动化配置

4)、启动 WEB 服务器

下面我们以 WEB 环境为例,通过源码来探讨其过程,刷新上下文入口在 SpringApplication 的 refresh 方法,源码如下:

	// 1、SpringApplication 的 refresh 方法protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);// web环境的话,这里调用的是 ServletWebServerApplicationContext 的 refresh 方法((AbstractApplicationContext) applicationContext).refresh();}// 2、ServletWebServerApplicationContext 的 refresh 方法@Overridepublic final void refresh() throws BeansException, IllegalStateException {try {// 调用 AbstractApplicationContext 的 refresh 方法super.refresh();}catch (RuntimeException ex) {stopAndReleaseWebServer();throw ex;}}

AbstractApplicationContext 的 refresh 方法实现的所有逻辑我们已经在 Spring源码系列之ApplicationContext refresh 刷新 中讲解过了,这里不在重复分析和Spring做了同样事情的步骤,只分析 Spring Boot 主要实现的自己关键业务步骤,即 onRefresh 方法、finishBeanFactoryInitialization 方法 finishRefresh 方法,下面分别介绍

3.3.1 onRefresh 方法

Spring Boot 的 onRefresh 方法主要实现了创建WEB服务器并启动Server和Service功能,入口在 ServletWebServerApplicationContext 的 onRefresh 方法,源码如下:

	// 1、ServletWebServerApplicationContext 的 onRefresh 方法@Overrideprotected void onRefresh() {// 初始化上下文主题资源super.onRefresh();try {// 创建WEB服务器createWebServer();}catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex);}}// 2、ServletWebServerApplicationContext 的 createWebServer 方法private void createWebServer() {WebServer webServer = this.webServer;ServletContext servletContext = getServletContext();if (webServer == null && servletContext == null) {// 获取 ServletWebServerFactory 实例ServletWebServerFactory factory = getWebServerFactory();// getSelfInitializer 方法初始化 ServletContext// ServletWebServerFactory(TomcatServletWebServerFactory) 的 getWebServer 方法获取 web 服务器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();}// 3、ServletContextInitializer 的 getSelfInitializer 方法private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {return this::selfInitialize;}// 4、ServletContextInitializer 的 getSelfInitializer 方法private void selfInitialize(ServletContext servletContext) throws ServletException {// ServletContext 属性设置prepareWebApplicationContext(servletContext);// BeanFactory 中注册 application 类型的 scoperegisterApplicationScope(servletContext);WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(),servletContext);// ServletContextInitializer 的 onStartup 方法做初始化操作,// 例如 DispatcherServletRegistrationBean 的 onStartup 方法实现了 ServletContext 增加 DispatcherServlet,// TomcatEmbeddedContext 增加 dispatcherServlet 中配置的 url 与 Wrapper 的映射关系// FilterRegistrationBean 的 onStartup 方法实现了 ServletContext 增加 CharacterEncodingFilter、HiddenHttpMethodFilter、FormContentFilter// 和 RequestContextFilter,TomcatEmbeddedContext 增加 characterEncodingFilter、hiddenHttpMethodFilter、formContentFilter 和 requestContextFilter// 中配置的 url 组成的FilterMap// 总结:ServletContext 绑定 Servlet 与 Filter 的实现for (ServletContextInitializer beans : getServletContextInitializerBeans()) {beans.onStartup(servletContext);}}// 5、TomcatServletWebServerFactory 的 getWebServer 方法@Overridepublic WebServer getWebServer(ServletContextInitializer... initializers) {Tomcat tomcat = new Tomcat();File baseDir = (this.baseDirectory != null) ? this.baseDirectory: createTempDir("tomcat");tomcat.setBaseDir(baseDir.getAbsolutePath());Connector connector = new Connector(this.protocol);// Service 与 Connector 绑定,此时 Connector 不会启动tomcat.getService().addConnector(connector);// Connector 的 bindOnInit 属性值决定了是否立即启动 Socket 绑定套接字,如果是应用启动较慢,这里建议设置为 false,即应用启动之后再启动 Socket 绑定套接字监听customizeConnector(connector);tomcat.setConnector(connector);tomcat.getHost().setAutoDeploy(false);// Engine 中的 Pipeline 与 Valve 关系绑定configureEngine(tomcat.getEngine());for (Connector additionalConnector : this.additionalTomcatConnectors) {// Service 与 Connector 绑定tomcat.getService().addConnector(additionalConnector);}// 创建并初始化设置 TomcatEmbeddedContextprepareContext(tomcat.getHost(), initializers);// 初始化 tomcat web 服务器,并返回 TomcatWebServerreturn getTomcatWebServer(tomcat);}// 6、TomcatServletWebServerFactory 的 getTomcatWebServer 方法protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {return new TomcatWebServer(tomcat, getPort() >= 0);}// 7、TomcatWebServer 的构造方法public TomcatWebServer(Tomcat tomcat, boolean autoStart) {Assert.notNull(tomcat, "Tomcat Server must not be null");this.tomcat = tomcat;this.autoStart = autoStart;// 启动 tomcat 服务initialize();}// 8、TomcatWebServer 的 initialize 方法private void initialize() throws WebServerException {logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));synchronized (this.monitor) {try {addInstanceIdToEngineName();Context context = findContext();context.addLifecycleListener((event) -> {if (context.equals(event.getSource())&& Lifecycle.START_EVENT.equals(event.getType())) {// Remove service connectors so that protocol binding doesn't// happen when the service is started.// 这里将 Service 和 Connector 关系移除了,防止启动 Service 时将 Connector 启动,这里就是将tomcat的真正启动放在了应用启动之后,提高性能removeServiceConnectors();}});// Start the server to trigger initialization listeners// 启动 tomcat 服务器,并触发初始化监听器// 注意这里只启动了 Server 和 Service,而没有启动 Connector 和 Socket 套接字,等到应用启动完成之后再启动 Connector 和 Socketthis.tomcat.start();// We can re-throw failure exception directly in the main threadrethrowDeferredStartupExceptions();try {ContextBindings.bindClassLoader(context, context.getNamingToken(),getClass().getClassLoader());}catch (NamingException ex) {// Naming is not enabled. Continue}// Unlike Jetty, all Tomcat threads are daemon threads. We create a// blocking non-daemon to stop immediate shutdownstartDaemonAwaitThread();}catch (Exception ex) {stopSilently();throw new WebServerException("Unable to start embedded Tomcat", ex);}}}

onRefresh 方法主要实现了以下逻辑:

1)、创建 ServletContext ,并绑定 DispatcherServlet 和 Filter

2)、创建 tomcat web 服务器并启动 tomcat,这里为了性能优化,通过设置 Connector 的 bindOnInit 属性为false来禁止完全启动 tomcat,这里只启动了 Tomcat 的 Server 和 Service,待应用启动好之后再启动 tomcat,即启动 Connector 和 Socket 套接字

3.3.2  finishBeanFactoryInitialization 方法

finishBeanFactoryInitialization 方法同样加载了所有非lazy的Singleton Bean,Spring Boot 正是在此过程中实现了自动化配置的加载,这个是 Spring Boot 的核心,我们在下一节对其单独分析,这里不在赘述了

3.3.3  finishRefresh 方法

Spring Boot 的 finishRefresh 方法除了实现Spring原有方法的逻辑之外,还实现了完全启动WEB服务器(启动 Tomcat 的 Connector 和 Socket 套接字)功能,入口在 ServletWebServerApplicationContext 的 finishRefresh 方法,源码如下:

	// 1、ServletWebServerApplicationContext 的 finishRefresh 方法@Overrideprotected void finishRefresh() {// Spring 原有方法的逻辑,这里不在分析super.finishRefresh();// 启动web服务器WebServer webServer = startWebServer();if (webServer != null) {// 发布 ServletWebServerInitializedEvent 事件,即宣告web应用启动完成publishEvent(new ServletWebServerInitializedEvent(webServer, this));}}// 2、ServletWebServerApplicationContext 的 startWebServer 方法private WebServer startWebServer() {WebServer webServer = this.webServer;if (webServer != null) {// 调用 WebServer(TomcatWebServer) 的 start 方法启动服务webServer.start();}return webServer;}// 3、TomcatWebServer 的 start 方法@Overridepublic void start() throws WebServerException {//  加对象锁,防止重复启动synchronized (this.monitor) {if (this.started) {return;}try {// connector 与 service 重新绑定,并启动 Connector,从而打开 Socket 套接字 完成 tomcat 的整个启动addPreviouslyRemovedConnectors();Connector connector = this.tomcat.getConnector();if (connector != null && this.autoStart) {// 加载 ServletperformDeferredLoadOnStartup();}checkThatConnectorsHaveStarted();this.started = true;logger.info("Tomcat started on port(s): " + getPortsDescription(true)+ " with context path '" + getContextPath() + "'");}catch (ConnectorStartFailedException ex) {stopSilently();throw ex;}catch (Exception ex) {throw new WebServerException("Unable to start embedded Tomcat server",ex);}finally {Context context = findContext();ContextBindings.unbindClassLoader(context, context.getNamingToken(),getClass().getClassLoader());}}}// 4、TomcatWebServer 的 addPreviouslyRemovedConnectors 方法private void addPreviouslyRemovedConnectors() {Service[] services = this.tomcat.getServer().findServices();for (Service service : services) {Connector[] connectors = this.serviceConnectors.get(service);if (connectors != null) {for (Connector connector : connectors) {// connector 与 service 绑定,并启动 Connector,从而打开 Socket 套接字 完成 tomcat 的整个启动service.addConnector(connector);if (!this.autoStart) {stopProtocolHandler(connector);}}// 启动 tomcat 完成之后,移除缓存this.serviceConnectors.remove(service);}}}

finishRefresh 方法主要实现了完全启动 Tomcat 服务器的功能,具体启动的是 Connector,进而打开 Socket 套接字来完成 tomcat 的整个启动

四、总结

Spring Boot 的启动过程不是特别复杂,其中最难理解的就是 Tomcat 的启动,Tomcat 的启动分为了两部分,在 onRefresh 方法时启动了 Tomcat 的 Server 和 Service,而在 finishRefresh 方法中启动了 Tomcat 的 Connector,从而达到了待应用启动之后再完全启动 Tomcat 服务器的目的,这样做是为了防止应用启动过慢导致整个服务启动慢而优化的

如果大家想学习 tomcat 的启动过程,请查看 tomcat9源码 写篇文章

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. PEP8 规范

    参考来源...

    2024/5/6 20:16:25
  2. 判断一个js对象,是否具有某个属性

    本文转载自:https://www.cnblogs.com/xiayu25/p/6242445.html 作者:xiayu25 转载请注明该声明。一个对象,想必我们关注的最多的应该是它上面的属性有哪些吧。那么,怎么判断一个对象是否具有某个属性呢? 1 /*下面是一个对比,看看在判断是否包括一个键上面,Object结构和S…...

    2024/5/6 20:16:22
  3. 拦截XSS攻击

    话不多说直接上代码@Configuration public class XssConfiguration {/*** 描述 : xssObjectMapper** @param builder builder* @return xssObjectMapper*/@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")@Bean@Primarypublic ObjectMapper xssO…...

    2024/5/6 20:16:17
  4. 物联网智能数据处理技术

    它是属于哪一层呢?自然是应用层中的管理服务层。下面我们就来介绍一下管理服务层的智能决策功能——基于对物联网数据的智能处理技术。 物联网数据的特点——要处理数据,先要认清数据海量 假如无线传感器网络中有 1000 个节点,每个传感器每分钟传输的数据是 1KB ,那么每一天…...

    2024/5/6 20:16:13
  5. 林大OJ习题 2020年1月2日

    林大OJ 572 密码箱 #include <iostream> #include <bits/stdc++.h> using namespace std;int main() {int n;while(scanf("%d",&n)!=EOF){for(n=n+1; n<1000; n++){if(n<10){printf("00%d\n",n);}if(n<100&&n>=10){pr…...

    2024/5/6 20:16:10
  6. vue中使用aes加密

    1、安装npm install crypto-js2、创建aes.js文件我是放在src/utils/aes.js3、aes页面引入方法import CryptoJS from crypto-js/crypto-js/** 默认的 KEY IV 如果在加密解密的时候没有传入KEY和IV,就会使用这里定义的* * 前后端交互时需要前后端密钥和初始向量保持一致*/con…...

    2024/5/6 8:38:06
  7. MySQL配置skip-name-resolve后连接时报错:"Host '127.0.0.1' is not allowed to connect to this

    MySQL版本:5.7.28jdk版本:1.7_80错误信息:Caused by: java.sql.SQLException: null, message from server: "Host 127.0.0.1 is not allowed to connect to this MySQL server"原因:是my.cnf加入了 skip-name-resolve 配置网上找了下资料,是用于mysql对连接的…...

    2024/5/6 20:16:05
  8. 搭建springboot框架并实现简单小demo出现问题

    1.在搭建springboot框架时要修改名字,否则会出现意外的惊喜。2.springboot 后台报错Error parsing HTTP request header Note: further occurrences of HTTP header .......原因及解决方案:在输入网址的时候,浏览器自动在前面加了https,但是由于域名没有ssl认证,所以会报…...

    2024/5/6 20:16:01
  9. 搞定响应式布局

    最近有的小伙伴面试会被问到响应式布局媒体查询的相关知识,这篇博文我就来给大家总结一下响应式布局的相关知识。 响应式布局是什么呢? 响应式布局时2010年5月份提出来的一个概念。是指根据不同设备浏览器分辨率或尺寸来展示不同页面结构、行为、表现的设计方式。例如我们用电…...

    2024/5/6 19:08:03
  10. 元学习系列(八):Reptile

    MAML主要就是学习一个网络的初始化参数,这个参数对梯度是敏感的,使得它在针对特定任务进行fine tuning时,只需要少数几次的训练就能达到较好的效果。 一般来说,我们可以用公式表示meta learning: minimize Eτ(Lτ(Uτk(ϕ)))minimize \ E_{\tau}(L_{\tau} (U_{\tau}^k(\p…...

    2024/5/6 20:15:53
  11. Git --- 常用指令操作

    一、查看当前状态git status 用于知道自己当前对仓库操作到哪一步了; 1、下图的提示是我当前什么提交操作都没有2、如果我在仓库新建了个readme.txt的文件,再次进行该命令; 会提示我说目前没有任何提交,但是会有N个文件将会被提交;二、添加到缓存区git add 1、添加单个文件…...

    2024/5/6 20:15:50
  12. redis 源码系列(6):实现简单又能打 --- skiplist

    跳跃表(skiplist)是一种高级数据结构,其插入、检索、删除的时间复杂度均为 O(logN)。因为其实实现简单,很多项目将其作为红黑树的一个替代品。 今天我们来看一下 redis 中 skiplist 的实现,涉及到的文件在 src/t_zset.c 和 src/redis.h。 redis 中的跳表基本上与常见跳表有…...

    2024/5/6 20:15:45
  13. AWS NLB 安全组配置问题

    AWS NLB 安全组配置问题 NLB, Network Load Balancer ,网络负载均衡器。 由于 NLB 没有安全组,所以需要将 NLB 所在 的 VPC 或者 NLB 的私网 IP 配置到 目标群组 的安全组上。 我尝试了如下几种配置配置 VPC 的 CIDR 到 目标群组的 安全组 ,无法通过 NLB 访问 目标群组 配置…...

    2024/5/6 20:15:42
  14. 韩信点兵

    题目 相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入包含多组数据,每组数据包含3个非负整数a,b,c,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最…...

    2024/5/6 20:15:37
  15. 今天和大家聊聊程序员职业发展的事~Java

    hello,各位同学们大家好,我是姚半仙。《Java架构师成长直通车》课程架构师讲师团成员之一。今天依然想和同学们谈一谈技术以外的东西,那谈些什么了? 职业发展 我想大部分做技术的同学,都是两耳不闻窗外事,一心只读圣贤书。大家多关注技术方面的发展,却忽视了在职业路线上…...

    2024/5/6 20:15:34
  16. arduino学习与实践

    如何使用电机驱动器 官网...

    2024/5/6 20:15:29
  17. 15.收货地址接口

    12.6收货地址接口 12.6.1wx.chooseAddress(Object object)基础库 1.1.0 开始支持,低版本需做兼容处理。调用前需要 用户授权 scope.address获取用户收货地址。调起用户编辑收货地址原生界面,并在编辑完成后返回用户选择的地址。 参数 Object object属性 类型 默认值 必填 说明…...

    2024/5/6 20:15:25
  18. modelsim添加vivado仿真库的方法

    转载 由于vivado自带仿真工具运行速度较慢,有时候需要在modelsim环境下仿真xilinx的ip,因此需要将xilinx的ip重新编译并添加至modelsim。首先需要重新编译xilinx的ip(以vivado2016.4为例,其余版本大同小异):tools -> Comple Simulation Libraries -> 设置编译…...

    2024/5/6 20:15:21
  19. SofaBoot使用Nacos进行服务注册发现

    前提 最近创业公司的项目组基于业务需要,开发一套新的微服务,考虑到选用的组件必须是主流、社区活跃、生态完善以及方便迁移到云上等因素,引入了SOFAStack全家桶。微服务开发里面,一个很重要的功能就是服务发现与注册,笔者花了点时间做了一个SOFABoot、SOFARpc结合Nacos实…...

    2024/5/6 20:15:17
  20. 实现类似ios闹钟设置界面选择时间效果

    滑动选择时间效果 using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems;public class Test1 : MonoBehaviour,IBeginDragHandler,IDragHandler {/// <summary>/// 根据手指滑动距离得出一个比率来计算方法执行次数/// </summary>public Text…...

    2024/5/6 20:15:13

最新文章

  1. 语音识别---节拍器

    ⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…...

    2024/5/6 21:24:43
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/6 9:38:23
  3. vscode安装通义灵码

    作为vscode的插件&#xff0c;直接使用 通义灵码-灵动指间&#xff0c;快码加编&#xff0c;你的智能编码助手 通义灵码&#xff0c;是一款基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研…...

    2024/5/6 2:26:42
  4. Docke搭建Lidarr

    Lidarr 是一个基于音乐的下载管理器&#xff0c;它可以监控多个 RSS 订阅源以查找用户指定类型的音乐并与支持的下载客户端协同工作。Lidarr 旨在自动化音乐下载过程&#xff0c;并整合到用户的音乐库中。它可以搜索歌曲&#xff0c;自动下载和整理音乐文件&#xff0c;更新元数…...

    2024/5/5 15:06:44
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/4 23:54:56
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/6 9:21:00
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/4 23:55:06
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/4 23:55:01
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57