SpringBoot启动流程源码解析

目录

一、SpringApplication构造方法解析

1. web应用类型

2. BootstrapRegistryInitializer

3. ApplicationContextInitializer

4. ApplicationListener

5. 推断Main方法所在类

二、SpringApplication.run(String... args)方法解析

1.创建DefaultBootstrapContext

2.获取SpringApplicationRunListeners

3.调用SpringApplicationRunListener的starting()

4.创建和配置Environment

5.配置需要忽略的Bean

6.打印Banner

7.创建ApplicationContext(Spring容器)

8.准备ApplicationContext(Spring容器)

8.1 ApplicationContextInitializer初始化Spring容器

8.2 SpringApplicationRunListener的contextPrepared()

8.3 DefaultBootstrapContext调用close()

8.4 load()方法将启动类作为配置类注册到Spring容器

8.5 SpringApplicationRunListener的contextLoaded()

9. 刷新ApplicationContext(Spring容器)

10. SpringApplicationRunListener的started()

11. 执行Runners

12. SpringApplicationRunListener的running()

13. 出现异常执行SpringApplicationRunListener的failed()



一、SpringApplication构造方法解析

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		this.bootstrapRegistryInitializers = new ArrayList<>(
				getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

1. web应用类型

private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
			"org.springframework.web.context.ConfigurableWebApplicationContext" };

	private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

	private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

	private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

	static WebApplicationType deduceFromClasspath() {
		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
			return WebApplicationType.REACTIVE;
		}
		for (String className : SERVLET_INDICATOR_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}

        如果项目依赖中存在org.springframework.web.reactive.DispatcherHandler,同时不存在org.springframework.web.servlet.DispatcherServlet,那么应用类型为WebApplicationType.REACTIVE

        如果项目依赖中不存在org.springframework.web.reactive.DispatcherHandler,同时也不存在org.springframework.web.servlet.DispatcherServlet,那么应用类型为WebApplicationType.NONE

        否则,应用类型为WebApplicationType.SERVLET

2. BootstrapRegistryInitializer

        从META-INF/spring.factories中读取键值为BootstrapRegistryInitializer类型的扩展点,并实例化出对应扩展对象实例

        BootstrapRegistryInitializer的作用是可以初始化BootstrapRegistry

        BootstrapRegistry时一个简单的对象注册表,在启动和 Environment 处理期间可用,直到准备完成 ApplicationContext(Spring 容器) 为止。可用于注册创建实例,或者完成ApplicationContext (Spring 容器)后共享一些实例

3. ApplicationContextInitializer

        从META-INF/spring.factories中读取键值为ApplicationContextInitializer类型的扩展点,并实例化出对应扩展对象实例

        ApplicationContextInitializer是用来初始化Spring容器ApplicationContext对象的,比如可以利用ApplicationContextInitializer来向Spring容器中添加ApplicationListener

4. ApplicationListener

        从"META-INF/spring.factories"中读取键值为ApplicationListener类型的扩展点,并实例化出对应扩展对象

5. 推断Main方法所在类

private Class<?> deduceMainApplicationClass() {
		try {
			StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
			for (StackTraceElement stackTraceElement : stackTrace) {
				if ("main".equals(stackTraceElement.getMethodName())) {
					return Class.forName(stackTraceElement.getClassName());
				}
			}
		}
		catch (ClassNotFoundException ex) {
			// Swallow and continue
		}
		return null;
	}

根据当前线程的调用栈来判断main()方法在哪个类,哪个类就是Main类。

二、SpringApplication.run(String... args)方法解析

public ConfigurableApplicationContext run(String... args) {
		long startTime = System.nanoTime();
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
			}
			listeners.started(context, timeTakenToStartup);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
			listeners.ready(context, timeTakenToReady);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

1.创建DefaultBootstrapContext

        使用SpringApplication构造方法中创建的BootstrapRegistryInitializer初始化DefaultBootstrapContext对象

2.获取SpringApplicationRunListeners

        从"META-INF/spring.factories"中读取键值为SpringApplicationRunListeners类型的扩展点,并实例化出对应扩展对象

3.调用SpringApplicationRunListener的starting()

        SpringBoot默认提供了一个EventPublishingRunListener,它实现了SpringApplicationRunListener接口,默认情况下会利用EventPublishingRunListener发布一个ApplicationStartingEvent事件,可以通过定义ApplicationListener来消费监听这个事件

4.创建和配置Environment

        Environment对象表示环境变量,该对象内部主要包含了:操作系统环境变量、JVM配置信息、-D方式所配置的JVM环境变量

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
		listeners.environmentPrepared(bootstrapContext, environment);
		DefaultPropertiesPropertySource.moveToEnd(environment);
		Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
				"Environment prefix cannot be set via properties.");
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
			environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

        SpringApplicationRunListener的environmentPrepared()

        默认情况下会利用EventPublishingRunListener发布一个ApplicationEnvironmentPreparedEvent事件,可以通过定义ApplicationListener来消费这个事件,比如默认情况下会有一个EnvironmentPostProcessorApplicationListener来消费这个事件,而这个ApplicationListener接收到这个事件之后,就会解析application.properties、application.yml文件并添加到Environment对象中。

5.配置需要忽略的Bean

public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beaninfo.ignore";

private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
		if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
			Boolean ignore = environment.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
					Boolean.class, Boolean.TRUE);
			System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
		}
	}

6.打印Banner

        SpringApplicationBannerPrinter

7.创建ApplicationContext(Spring容器)

        使用ApplicationContextFactory.DEFAULT根据应用类型创建对应的Spring容器

public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
			return (webApplicationType != WebApplicationType.SERVLET) ? null
					: new AnnotationConfigServletWebServerApplicationContext();
		}

        应用类型为SERVLET,则对应AnnotationConfigServletWebServerApplicationContext

        应用类型为REACTIVE,则对应AnnotationConfigReactiveWebServerApplicationContext

        应用类型为普通类型,则对应AnnotationConfigApplicationContext

        一般使用的应用类型为SERVLET:AnnotationConfigServletWebServerApplicationContext

8.准备ApplicationContext(Spring容器)

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
		context.setEnvironment(environment);
		postProcessApplicationContext(context);
		applyInitializers(context);
		listeners.contextPrepared(context);
		bootstrapContext.close(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// Add boot specific singleton beans
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		if (printedBanner != null) {
			beanFactory.registerSingleton("springBootBanner", printedBanner);
		}
		if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
			((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
			if (beanFactory instanceof DefaultListableBeanFactory) {
				((DefaultListableBeanFactory) beanFactory)
					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
			}
		}
		if (this.lazyInitialization) {
			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		}
		context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
		// Load the sources
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		load(context, sources.toArray(new Object[0]));
		listeners.contextLoaded(context);
	}

8.1 ApplicationContextInitializer初始化Spring容器

        默认SpringBoot提供了多个ApplicationContextInitializer,其中比较重要的有ConditionEvaluationReportLoggingListener

@Override
	public void initialize(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		applicationContext.addApplicationListener(new ConditionEvaluationReportListener());
		if (applicationContext instanceof GenericApplicationContext) {
			// Get the report early in case the context fails to load
			this.report = ConditionEvaluationReport.get(this.applicationContext.getBeanFactory());
		}
	}

        在该类的initialize()方法中:

        将Spring容器赋值给它的applicationContext属性

        并且往Spring容器中添加一个ConditionEvaluationReportListener(ConditionEvaluationReportLoggingListener的内部类),它是一个ApplicationListener

        并生成一个ConditionEvaluationReport对象赋值给它的report属性

        ConditionEvaluationReportListener会负责接收ContextRefreshedEvent事件,也就是Spring容器启动完毕就会触发ContextRefreshedEvent,ConditionEvaluationReportListener就会打印自动配置类的条件评估报告。

	protected void onApplicationEvent(ApplicationEvent event) {
		ConfigurableApplicationContext initializerApplicationContext = this.applicationContext;
		if (event instanceof ContextRefreshedEvent) {
			if (((ApplicationContextEvent) event).getApplicationContext() == initializerApplicationContext) {
				logAutoConfigurationReport();
			}
		}
		else if (event instanceof ApplicationFailedEvent
				&& ((ApplicationFailedEvent) event).getApplicationContext() == initializerApplicationContext) {
			logAutoConfigurationReport(true);
		}
	}

8.2 SpringApplicationRunListener的contextPrepared()

        默认会利用EventPublishingRunListener发布一个ApplicationContextInitializedEvent事件,默认情况没有ApplicationListener消费该事件

8.3 DefaultBootstrapContext调用close()

        关闭时要调用BootstrapContext的方法


8.4 load()方法将启动类作为配置类注册到Spring容器

8.5 SpringApplicationRunListener的contextLoaded()

        默认会利用EventPublishingRunListener发布一个ApplicationPreparedEvent事件

	@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));
	}

9. 刷新ApplicationContext(Spring容器)

        调用Spring容器的refresh()方法:

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// 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);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// 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.
				finishRefresh();
			}

			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();
				contextRefresh.end();
			}
		}
	}

        ServletWebServerApplicationContext在重写onRefresh方法,在该方法中创建了WebServer,默认启动Tomcat服务器。

@Override
	protected void onRefresh() {
		super.onRefresh();
		try {
			createWebServer();
		}
		catch (Throwable ex) {
			throw new ApplicationContextException("Unable to start web server", ex);
		}
	}

10. SpringApplicationRunListener的started()

        发布ApplicationStartedEvent事件和AvailabilityChangeEvent事件,AvailabilityChangeEvent事件表示状态变更状态,变更后的状态为LivenessState.CORRECT

@Override
	public void started(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
	}

public enum LivenessState implements AvailabilityState {

	/**
	 * The application is running and its internal state is correct.
	 */
	CORRECT,

	/**
	 * The application is running but its internal state is broken.
	 */
	BROKEN

}

11. 执行Runners

        获取Spring容器中的ApplicationRunner和CommandLineRunner类型的Bean,然后按顺序调用他们的run()方法

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);
			}
		}
	}

12. SpringApplicationRunListener的running()

        发布ApplicationReadyEvent事件和AvailabilityChangeEvent事件,AvailabilityChangeEvent事件表示状态变更状态,变更后的状态为ReadinessState.ACCEPTING_TRAFFIC

@Override
	public void running(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
	}

public enum ReadinessState implements AvailabilityState {

	/**
	 * The application is ready to receive traffic.
	 */
	ACCEPTING_TRAFFIC,

	/**
	 * The application is not willing to receive traffic.
	 */
	REFUSING_TRAFFIC

}

13. 出现异常执行SpringApplicationRunListener的failed()

        发布ApplicationFailedEvent事件

@Override
	public void failed(ConfigurableApplicationContext context, Throwable exception) {
		ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
		if (context != null && context.isActive()) {
			// Listeners have been registered to the application context so we should
			// use it at this point if we can
			context.publishEvent(event);
		}
		else {
			// An inactive context may not have a multicaster so we use our multicaster to
			// call all of the context's listeners instead
			if (context instanceof AbstractApplicationContext) {
				for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
						.getApplicationListeners()) {
					this.initialMulticaster.addApplicationListener(listener);
				}
			}
			this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
			this.initialMulticaster.multicastEvent(event);
		}
	}

至此Springboot的启动执行流程全部完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/606293.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

回顾5款我非常喜欢的软件,希望大家也能喜欢

​ 我喜欢分享好软件,这就像与老友聊天一样让我感到快乐。在这个过程中,我可以回顾这些实用的小工具,也希望它们可以帮助到更多人。 1.备份工具——Cobian Backup ​ Cobian Backup是一款功能强大的备份软件&#xff0c;支持自动定时备份、增量备份、差异备份等多种备份方式。…

Java八股文系列之四(JVM)

什么是Java虚拟机&#xff1f;为什么Java被称作是“平台无关的编程语言”&#xff1f; Java虚拟机是一个可以执行Java字节码的虚拟机进程。 Java 实现跨平台的主要原因在于它的编译和执行方式。Java 程序首先被编译成中间代码&#xff08;bytecode&#xff09;&#xff0c;然…

九泰智库 | 医械周刊- Vol.26

⚖️ 法规动态 国家卫健委等八部门印发《关于加强重症医学医疗服务能力建设的意见》 5月6日&#xff0c;国家卫健委发布《关于加强重症医学医疗服务能力建设的意见》&#xff0c;明确我国重症医学领域的重要部署。数据显示&#xff0c;我国在重症救治设备方面依然存在巨大缺口…

vue中使用element的i18n语言转换(保姆式教程-保证能用)

1、项目中需要使用的插件&#xff0c;vue2或vue3、element、vue-i18n、js-cookie、vuex我是在vue2中使用 npm i element-ui -S npm i js-cookie -S npm i vue-i18n8.28.2 //因为我项目使用的vue2&#xff0c;直接安装报错了,就下载了固定的版本2、在main.js中引入i18n impor…

芸众商城电商专业版400+插件源码+搭建教程

介绍&#xff1a; 芸众商城社交电商系统SAAS平台前端基于vue开发&#xff0c;后端基于研发积分商城系统源码 php&#xff0c;本文安装芸众商城全插件&#xff08;400多个&#xff09;商业版平台源码&#xff0c;可同时支持多端口部署运行&#xff1b;使用宝塔面板一键部署的形…

出货300万片后,智舱界「小高通」浮出水面

‍作者 |张祥威 编辑 |德新 2024年北京车展&#xff0c;本土芯片公司开始截击外企供应商。 很长一段时间内&#xff0c;汽车行业智驾芯片看英伟达&#xff0c;座舱芯片看高通。英伟达Orin系列广受欢迎&#xff0c;高通8155席卷主流智能汽车&#xff0c;8295更是被视为最强配置…

倍思|西圣开放式耳机哪个好用?热门机型深度测评!

在数字化生活的浪潮中&#xff0c;耳机已成为我们不可或缺的伴侣。然而&#xff0c;长时间佩戴传统的耳机容易导致的耳道疼痛等问题&#xff0c;严重的话将影响听力。许多人开始寻找更为舒适的佩戴体验。开放式耳机因为不需要需直接插入耳道的设计&#xff0c;逐渐受到大众的青…

不会pdf修改编辑文字怎么办?看完秒懂

不会pdf修改编辑文字怎么办&#xff1f;在日常生活中&#xff0c;PDF文件已成为我们工作、学习不可或缺的一部分。然而&#xff0c;很多人对PDF文件的编辑操作感到困惑&#xff0c;尤其是修改其中的文字。今天&#xff0c;我们就来详细解析一下&#xff0c;不会PDF修改编辑文字…

全局变量在 Python 中的应用场景

在Python中&#xff0c;全局变量是在程序的全局范围内定义的变量&#xff0c;可以在整个程序中访问。虽然在Python中使用全局变量并不像在其他编程语言中那样被推荐&#xff0c;因为它可能导致代码不易理解和维护&#xff0c;但在一些特定的情况下&#xff0c;全局变量仍然是有…

企业微信hook接口协议,ipad协议http,设置是否自动同意

设置是否自动同意 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid":"bc4800492083fdec4c1a7e5c94","state":1 //1 是需要验证同意&#xff08;需要手动点击同意&#xff09; 0关闭验证…

gtest的编译与使用

文章目录 gtest的编译与使用概述笔记CMake参数官方文档测试程序测试效果END gtest的编译与使用 概述 gTest是 googletest的缩写&#xff0c;如果直接找gTest项目&#xff0c;是找不到的。 库地址 https://github.com/google/googletest.git 迁出到本地后&#xff0c;切到最新…

中电金信:看 “咨询+技术”如何引领数字化变革新风向

当前&#xff0c;新一轮创新技术和产业变革正在重塑全球的经济格局。日本政府及社会各界也从各个领域着手推进数字化。2021年&#xff0c;日本政府成立了“数字厅”&#xff0c;通过一系列举措推动数字化升级&#xff0c;希望将日本加速转型为数字经济的区域领导者&#xff0c;…

继续SQL

主知识点六&#xff1a;having 聚合前的筛选用where&#xff0c;聚合后的筛选用having Having和where的区别是&#xff1a;运行顺序和对象不用 Having是在group by聚合后的基础上进行筛选。 ● 【例题27*】&#xff08;运行原理&#xff09;查询总人口数至少为3亿的大洲和…

git的标签管理

理解标签 在Git中,标签tag用于标记特定的一个重要点&#xff0c;比如版本发布。标签允许捕捉某一次提交的状态&#xff0c;当我们需要退回到某次提叫的版本时&#xff0c;通过标签我们快速定位到。标签具有两种类型&#xff1a; 轻量标签&#xff1a;最简单的标签形式&#x…

QGIS编译

一&#xff0c;安装&#xff1a;OSGeo4W 二&#xff0c;安装&#xff1a;Cygwin64 https://www.cygwin.com/setup-x86_64.exe 三&#xff0c;安装&#xff1a; 安装bison和flex 四&#xff09;QGIS_3.28 下载QGIS_3.28的源码包 五 环境变量设置&#xff1a; echo off set VS19…

那些可免费使用的在线大语言模型服务

2022年底以ChatGPT[1]为代表的大语言模型的出现掀起了人工智能应用的新浪潮。这些庞大的语言模型经过对海量文本数据的训练&#xff0c;能够理解和生成逼近人类水平的自然语言&#xff0c;在对话、问答、文本生成、代码编写等领域展现出了惊人的能力。 最初这种能力“垄断”在O…

用手势掌控PPT,玩转演示新姿势

推荐运行环境 使用anaconda创建环境&#xff0c;以免污染原来的python开发环境conda install python3.9pip install -q mediapipe0.10.0pip install pyautoguiPython: version 3.8 - 3.11PIP: version 20.3 请注意以下的坑 以下为我测试过程中的大坑&#xff0c;请及时避开&am…

【2024高校网络安全管理运维赛】巨细记录!

2024高校网络安全管理运维赛 文章目录 2024高校网络安全管理运维赛MISC签到考点&#xff1a;动态图片分帧提取 easyshell考点&#xff1a;流量分析 冰蝎3.0 Webphpsql考点&#xff1a;sql万能钥匙 fileit考点&#xff1a;xml注入 外带 Cryptosecretbit考点&#xff1a;代码阅读…

Driftingblues靶机系列Driftingblues5

获取靶机的ip&#xff1a;192.168.108.37 扫描靶机的端口服务: 看到web服务和ssh服务&#xff1a; 先查看一下web服务&#xff1a; 扫描到web服务的信息&#xff1a; 访问web服务&#xff1a; 在源代码中并没有看到有什么新的信息&#xff0c;扫描一下靶机目录&#xff1a;…

vue地址选择器-三级联选择器+详细地址

在页面的显示情况 前端拼接实现存储 具体实现步骤 1.安装中国全省市区的数据 在命令提示符窗口使用管理员身份进入对应vue项目的文件夹&#xff0c;在窗口安装 npm install element-china-area-data -S2.在script内引入安装的数据 import {regionData,codeToText } from…
最新文章