run方法执行过程分析
文章目录
- run方法核心流程
- SpringApplicationRunListener监听器
- 监听器的配置与加载
- SpringApplicationRunListener源码解析
- 实现类EventPublishingRunListener
- 初始化ApplicationArguments
- 初始化ConfigurableEnvironment
- 获取或创建环境
- 配置环境
- 打印Banner
- Spring应用上下文的创建
- Spring应用上下文的准备
- Spring应用上下文的刷新
- 调用ApplicationRunner和CommandLineRunner
run方法核心流程
在分析和学习整个run方法的源代码及操作之前,我们先通过下图所示的流程图来看一下SpringApplication调用的run方法处理的核心操作都包含哪些。

上面的流程图可以看出,SpringApplication在run方法中重点做了以下操作。
- 获取监听器和参数配置。
- 打印Banner信息。
- 创建并初始化容器。
- 监听器发送通知。
当然,除了核心操作,run方法运行过程中还涉及启动时长统计、异常报告、启动日志、异常处理等辅助操作。
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();this.configureHeadlessProperty();SpringApplicationRunListeners listeners = this.getRunListeners(args);listeners.starting();Collection exceptionReporters;try {// 创建 ApplicationArguments 对象ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 加载属性配置ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);this.configureIgnoreBeanInfo(environment);// 打印bannerBanner printedBanner = this.printBanner(environment);// 创建容器context = this.createApplicationContext();// 异常报告器exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);// 准备容器this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);// 初始化容器this.refreshContext(context);// 初始化容器后this.afterRefresh(context, applicationArguments);// 停止时长统计stopWatch.stop();// 打印日志if (this.logStartupInfo) {(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);}// 通知监听器容器启动完成listeners.started(context);this.callRunners(context, applicationArguments);} catch (Throwable var10) {// 异常处理this.handleRunFailure(context, var10, exceptionReporters, listeners);throw new IllegalStateException(var10);}try {// 通知监听器:容器正在运行listeners.running(context);return context;} catch (Throwable var9) {// 异常处理this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);throw new IllegalStateException(var9);}
}
SpringApplicationRunListener监听器
监听器的配置与加载
SpringApplicationRunListeners 可以理解为一个SpringApplicationRunListener的容器,它将SpringApplicationRunListener的集合以构造方法传入,并赋值给其listeners成员变量,然后提供了针对listeners 成员变量的各种遍历操作方法,比如,遍历集合并调用对应的starting、started、running等方法。
SpringApplicationRunListeners 的构建很简单,SpringApplication中getRunListeners方法代码如下:
private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class[]{SpringApplication.class, String[].class};return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
SpringApplicationRunListeners构造方法的第二个参数便是SpringApplicationRunListener的集合,SpringApplication中调用构造方法时该参数是通过getSpringFactoriesInstances方法获取(都是一样的套路)的,代码如下:
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {// 获取类加载器ClassLoader classLoader = this.getClassLoader();// 加载监听器,并放入set中Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 实例化监听器List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);// 排序AnnotationAwareOrderComparator.sort(instances);return instances;
}
通过方法名便可得知,getSpringFactoriesInstances是用来获取factories配置文件中的注册类,并进行实例化操作。
关于通过SpringFactoriesLoader获取META-INF/spring.factories中对应的配置,构造方法章节已经多次提到,这里不再赞述。SpringApplicationRunListener的注册配置位于spring-boot项目中的spring.factories文件内,SpringBoot默认仅有一个监听器进行了注册,关于其功能后面会专门讲到。
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {List<T> instances = new ArrayList(names.size());Iterator var7 = names.iterator();while(var7.hasNext()) {String name = (String)var7.next();try {Class<?> instanceClass = ClassUtils.forName(name, classLoader);Assert.isAssignable(type, instanceClass);Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);T instance = BeanUtils.instantiateClass(constructor, args);instances.add(instance);} catch (Throwable var12) {throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);}}return instances;
}
在上面的代码中,实例化监听器时需要有一个默认的构造方法,且构造方法的参数为Class<?>[]parameterTypes。我们向上追踪该参数的来源,会发现该参数的值为Class数组,数组的内容依次为SpringApplication.class和String[].class。也就是说,SpringApplicationRunListener的实现类必须有默认的构造方法,且构造方法的参数必须依次为SpringApplication和String[]类型。
SpringApplicationRunListener源码解析
接口SpringApplicationRunListener是SpringApplication的run方法监听器。上节提到了 SpringApplicationRunListener通过SpringFactoriesLoader加载,并且必须声明一个公共构造函数,该函数接收SpringApplication实例和String[]的参数,而且每次运行都会创建一个新的实例。
SpringApplicationRunListener提供了一系列的方法,用户可以通过回调这些方法,在启动各个流程时加入指定的逻辑处理。
class SpringApplicationRunListeners {private final Log log;private final List<SpringApplicationRunListener> listeners;SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {this.log = log;this.listeners = new ArrayList(listeners);}public void starting() {Iterator var1 = this.listeners.iterator();while(var1.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();listener.starting();}}public void environmentPrepared(ConfigurableEnvironment environment) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.environmentPrepared(environment);}}public void contextPrepared(ConfigurableApplicationContext context) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.contextPrepared(context);}}public void contextLoaded(ConfigurableApplicationContext context) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.contextLoaded(context);}}public void started(ConfigurableApplicationContext context) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.started(context);}}public void running(ConfigurableApplicationContext context) {Iterator var2 = this.listeners.iterator();while(var2.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();listener.running(context);}}public void failed(ConfigurableApplicationContext context, Throwable exception) {Iterator var3 = this.listeners.iterator();while(var3.hasNext()) {SpringApplicationRunListener listener = (SpringApplicationRunListener)var3.next();this.callFailedListener(listener, context, exception);}}private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context, Throwable exception) {try {listener.failed(context, exception);} catch (Throwable var6) {if (exception == null) {ReflectionUtils.rethrowRuntimeException(var6);}if (this.log.isDebugEnabled()) {this.log.error("Error handling failed", var6);} else {String message = var6.getMessage();message = message != null ? message : "no error message";this.log.warn("Error handling failed (" + message + ")");}}}
}
我们通过源代码可以看出,SpringApplicationRunListener为run方法提供了各个运行阶段的监听事件处理功能。
下图展示了在整个run方法的生命周期中SpringApplicationRunListener的所有方法所处的位置,该图可以帮助我们更好地学习run方法的运行流程。在前面run方法的代码中已经看到相关监听方法被调用,后续的源代码中也将涉及对应方法的调用,我们可参考此图以便理解和加深记忆。

实现类EventPublishingRunListener
EventPublishingRunListener是SpringBoot中针对SpringApplicationRunListener接口的唯一内建实现。EventPublishingRunListener使用内置的SimpleApplicationEventMulticaster来广播在上下文刷新之前触发的事件。
默认情况下,SpringBoot在初始化过程中触发的事件也是交由EventPublishingRunListener来代理实现的。
SpringBoot完成基本的初始化之后,会遍历SpringApplication的所有ApplicationListener实例,并将它们与SimpleApplicationEventMulticaster进行关联,方便SimpleApplicationEventMulticaster后续将事件传递给所有的监听器。
EventPublishingRunListener针对不同的事件提供了不同的处理方法,但它们的处理流程基本相同。
public void contextLoaded(ConfigurableApplicationContext context) {ApplicationListener listener;for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {listener = (ApplicationListener)var2.next();if (listener instanceof ApplicationContextAware) {((ApplicationContextAware)listener).setApplicationContext(context);}}this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
contextLoaded方法在发布事件之前做了两件事:第一,遍历application的所有监听器实现类,如果该实现类还实现了ApplicationContextAware接口,则将上下文信息设置到该监听器内;第二,将application中的监听器实现类全部添加到上下文中。最后一步才是调用事件广播。
也正是这个方法形成了不同事件广播形式的分水岭,在此方法之前执行的事件广播都是通过multicastEvent来进行的,而该方法之后的方法则均采用publishEvent来执行。这是因为只有到了contextLoaded方法之后,上下文才算初始化完成,才可通过它的publishEvent方法来进行事件的发布。
初始化ApplicationArguments
监听器启动之后,紧接着便是执行ApplicationArguments对象的初始化,ApplicationArguments是用于提供访问运行SpringApplication时的参数。
ApplicationArguments的初始化过程非常简单,只是调用了它的实现类DefaultApplicationArguments并传入main方法中的args参数。
在DefaultApplicationArguments中将参数args封装为Source对象,Source对象是基于Spring框架的SimpleCommandLinePropertySource来实现的。
初始化ConfigurableEnvironment
完成ApplicationArguments参数的准备之后,便开始通过prepareEnvironment方法对ConfigurableEnvironment对象进行初始化操作。
ConfigurableEnvironment接口继承自Environment接口和ConfigurablePropertyResolver,最终都继承自接口PropertyResolverConfigurableEnvironment接口的主要作用是提供当前运行环境的公开接口,比如配置文件profiles各类系统属性和变量的设置、添加、读取、合并等功能。
通过ConfigurableEnvironment接口中方法定义,可以更清楚地了解它的功能,代码如下:
public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {void setActiveProfiles(String... var1);void addActiveProfile(String var1);void setDefaultProfiles(String... var1);MutablePropertySources getPropertySources();Map<String, Object> getSystemProperties();Map<String, Object> getSystemEnvironment();void merge(ConfigurableEnvironment var1);
}
通过接口提供的方法,我们可以看出ConfigurableEnvironment就是围绕着这个“环境”来提供相应的功能,这也是为什么我们也将它称作“环境”。
了解了ConfigurableEnvironment的功能及方法,我们回归到SpringApplication的流程看相关源代码。run方法中调用prepareEnvironment方法相关代码如下:
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {ConfigurableEnvironment environment = this.getOrCreateEnvironment();this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());listeners.environmentPrepared((ConfigurableEnvironment)environment);this.bindToSpringApplication((ConfigurableEnvironment)environment);if (!this.isCustomEnvironment) {environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());}ConfigurationPropertySources.attach((Environment)environment);return (ConfigurableEnvironment)environment;
}
通过以上代码可知,prepareEnvironment进行了以下的操作:
- 获取或创建环境。
- 配置环境。
- ConfigurationPropertySources附加到指定环境:将ConfigurationPropertySources附加到指定环境中的第一位,并动态跟踪环境的添加或删除(当前版本新增了该行代码,与最后一步操作相同)。
- 设置listener监听事件:前面章节已经讲过,此处主要针对准备环境的监听。
- 绑定环境到SpringApplication:将环境绑定到name为“spring.main”的目标上。
- 转换环境:判断是否是定制的环境,如果不是定制的,则将环境转换为StandardEnvironment。此时判断条件isCustomEnvironment默认为false,在后面的操作中会将其设置为true,如果为true则不再会进行此转换操作。
- ConfigurationPropertySources附加到指定环境:将ConfigurationPropertySources附加到指定环境中的第一位,并动态跟踪环境的添加或删除操作。
获取或创建环境
SpringApplication类中通过getOrCreateEnvironment方法来获取或创建环境。在该方法中首先判断环境是否为null,如果不为null则直接返回;如果为null,则根据前面推断出来的WebApplicationType类型来创建指定的环境。
配置环境
在获得环境变量对象之后,开始对环境变量和参数进行相应的设置,主要包括转换服务的设置、PropertySources的设置和activeProfiles的设置。
打印Banner
完成环境的基本处理之后,下面就是控制台Banner的打印了。SpringBoot的Banner打印是一个比较酷炫的功能,但又显得有些华而不实,特别是打印图片时启动速度会变慢。
private Banner printBanner(ConfigurableEnvironment environment) {if (this.bannerMode == Mode.OFF) {return null;} else {ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader(this.getClassLoader());SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter((ResourceLoader)resourceLoader, this.banner);return this.bannerMode == Mode.LOG ? bannerPrinter.print(environment, this.mainApplicationClass, logger) : bannerPrinter.print(environment, this.mainApplicationClass, System.out);}
}
上面的代码中展示了Banner的开启及打印位置的设置。程序通过Banner.Mode枚举值来判断是否开启Banner打印,此项参数可以在SpringBoot入口nmain方法中通过setBannerMode方法来设置,也可以通过application.properties中的spring.main.banner-mode进行设置。
SpringApplicationBannerPrinter类承载了Banner初始化及打印的核心功能,比如默认如何获取Banner信息、如何根据约定优于配置来默认获得Banner的内容、Banner支持的文件格式等。
而具体打印的信息是由Banner接口的实现类来完成的,比如默认情况下使用SpringBootBanner来打印SpringBoot的版本信息及简单的图形。当然还有通过资源文件打印的ResourceBanner,通过图片打印的ImageBanner等方法。
Spring应用上下文的创建
SpringBoot创建Spring的应用上下文时,如果未指定要创建的类,则会根据之前推断出的类型来进行默认上下文类的创建。
在SpringBoot中通过SpringApplication类中的createApplicationContext来进行应用上下文的创建,代码如下:
protected ConfigurableApplicationContext createApplicationContext() {// 获取容器的类变量Class<?> contextClass = this.applicationContextClass;// 如果为null,则根据Web应用类型按照默认类进行创建if (contextClass == null) {try {switch(this.webApplicationType) {case SERVLET:contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");break;case REACTIVE:contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");break;default:contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");}} catch (ClassNotFoundException var3) {throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);}}return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
Spring应用上下文的准备
我们在上一节完成了应用上下文的创建工作,SpringApplication继续通过prepareContext方法来进行应用上下文的准备工作。
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {// 设置应用上下文环境context.setEnvironment(environment);// 设置应用上下文后置处理this.postProcessApplicationContext(context);// 初始化contextthis.applyInitializers(context);// 通知监听器上下文准备阶段listeners.contextPrepared(context);// 打印 profileif (this.logStartupInfo) {this.logStartupInfo(context.getParent() == null);this.logStartupProfileInfo(context);}// 获取 ConfigurableListableBeanFactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// 获取全部配置源Set<Object> sources = this.getAllSources();Assert.notEmpty(sources, "Sources must not be empty");// 将获取到的配置源加载到context中this.load(context, sources.toArray(new Object[0]));// 通知监听器 context 加载完成listeners.contextLoaded(context);
}
Spring应用上下文的刷新
Spring应用上下文的刷新,是通过调用SpringApplication中的refreshContext方法来完成的。SpringApplication中refreshContext方法相关代码如下:
private void refreshContext(ConfigurableApplicationContext context) {this.refresh(context);if (this.registerShutdownHook) {try {context.registerShutdownHook();} catch (AccessControlException var3) {}}}protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);((AbstractApplicationContext)applicationContext).refresh();
}
其中refresh方法调用的是AbstractApplicationContext中的refresh方法,该类属于spring-context包。AbstractApplicationContext的refresh方法更多的是Spring相关的内容。
public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {this.prepareRefresh();ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();this.prepareBeanFactory(beanFactory);try {this.postProcessBeanFactory(beanFactory);this.invokeBeanFactoryPostProcessors(beanFactory);this.registerBeanPostProcessors(beanFactory);this.initMessageSource();this.initApplicationEventMulticaster();this.onRefresh();this.registerListeners();this.finishBeanFactoryInitialization(beanFactory);this.finishRefresh();} catch (BeansException var9) {if (this.logger.isWarnEnabled()) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);}this.destroyBeans();this.cancelRefresh(var9);throw var9;} finally {this.resetCommonCaches();}}
}
在上面的代码中,调用finishRefresh方法初始化容器的生命周期处理器并发布容器的生命周期事件之后,Spring应用上下文正式开启,SpringBoot核心特性也随之启动。完成refreshContext方法操作之后,调用afterRefresh方法。
完成以上操作之后,调用SpringApplicationRunListeners的started方法,通知监听器容器启动完成,并调用ApplicationRunner和CommandLineRunner的运行方法。
调用ApplicationRunner和CommandLineRunner
ApplicationRunner和CommandLineRunner是通过 SpringApplication类的callRunners方法来完成的,具体代码如下:
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);Iterator var4 = (new LinkedHashSet(runners)).iterator();while(var4.hasNext()) {Object runner = var4.next();if (runner instanceof ApplicationRunner) {this.callRunner((ApplicationRunner)runner, args);}if (runner instanceof CommandLineRunner) {this.callRunner((CommandLineRunner)runner, args);}}}
以上代码,首先从context中获得类型为ApplicationRunner和CommandLineRunner的Bean,将它们放入List列表中并进行排序。然后再遍历调用其run方法,并将ApplicationArguments参数传入。
SpringBoot提供这两个接口的目的,是为了我们在开发的过程中,通过它们来实现在容器启动时执行一些操作,如果有多个实现类,可通过@Order注解或实现Ordered接口来控制执行顺序。
这两个接口都提供了一个run方法,但不同之处在于:ApplicationRunner中run方法的参数为ApplicationArguments,而CommandLineRunner接口中run方法的参数为String数组。
以上方法执行完成后,会通过SpringApplicationRunListeners的running方法通知监听器:容器此刻已处于运行状态。至此,SpringApplication的run方法执行完毕。
相关文章:
run方法执行过程分析
文章目录 run方法核心流程SpringApplicationRunListener监听器监听器的配置与加载SpringApplicationRunListener源码解析实现类EventPublishingRunListener 初始化ApplicationArguments初始化ConfigurableEnvironment获取或创建环境配置环境 打印BannerSpring应用上下文的创建S…...
面试-----每日一题
一、字节一面(操作系统) 什么是死锁?如何处理死锁问题? 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通讯而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。…...
学习与事务平衡技巧
当学习过程中需要处理其他事务时,关键在于平衡专注与灵活性,避免中断打乱学习节奏。以下是具体建议: 一、快速判断事务优先级 紧急且重要(如突发工作、紧急回复): 立刻处理,但完成后用5分钟快速…...
CentOS 7中安装Dify
Dify 是一个开源的 LLM 应用开发平台。其直观的界面结合了 AI 工作流、RAG 管道、Agent、模型管理、可观测性功能等,让您可以快速从原型到生产。尤其是我们本地部署DeepSeek等大模型时,会需要用到Dify来帮我们快捷的开发和应用。 大家可以参考学习它的中…...
qt-C++笔记之Linux下Qt环境变量设置及与QtCreator的关系
qt-C++笔记之Linux下Qt环境变量设置及与QtCreator的关系 code review! 文章目录 qt-C++笔记之Linux下Qt环境变量设置及与QtCreator的关系一.Qt关键的环境变量1.1.PATH1.2.LD_LIBRARY_PATH1.3.QML2_IMPORT_PATH二.若不手动设置这三个环境变量2.1.PATH 的默认路径2.2.LD_LIBRARY_…...
问deepseek:有哪些支持OpenMP多线程并行的AMG代数多重网格软件库
AMG(Algebraic Multigrid)是一种用于求解大规模稀疏线性方程组的有效方法,广泛应用于科学计算和工程领域。OpenMP 是一种用于共享内存并行编程的 API,支持多线程并行计算。 以下是一些支持 OpenMP 多线程的开源 AMG 软件包&#…...
【Flink银行反欺诈系统设计方案】1.短时间内多次大额交易场景的flink与cep的实现
【flink应用系列】1.Flink银行反欺诈系统设计方案 1. 经典案例:短时间内多次大额交易1.1 场景描述1.2 风险判定逻辑 2. 使用Flink实现2.1 实现思路2.2 代码实现2.3 使用Flink流处理 3. 使用Flink CEP实现3.1 实现思路3.2 代码实现 4. 总结 1. 经典案例:短…...
Android 系统开发的指导文档
Android 系统开发的指导文档 文章目录 Android 系统开发的指导文档一、基础准备1、学习编程语言2、熟悉开发环境 二、核心知识学习1、Android 系统架构:2、四大组件(1)Activity:是 Android 应用中最基本的组件,用于实现…...
网络编程——http
在Linux系统中使用C语言实现HTTP客户端或服务器通常涉及使用套接字编程和一些HTTP协议的基本知识。下面是一个简单的示例,展示了如何用C语言实现一个HTTP客户端,向一个HTTP服务器发送请求并接收响应。 1. HTTP客户端示例 (C语言) 这个例子展示了如何用C…...
Flutter 学习之旅 之 flutter 使用 carousel_slider 简单实现轮播图效果
Flutter 学习之旅 之 flutter 使用 carousel_slider 简单实现轮播图效果 目录 Flutter 学习之旅 之 flutter 使用 carousel_slider 简单实现轮播图效果 一、简单介绍 二、简单介绍 carousel_slider 三、安装 carousel_slider 四、简单案例实现 五、关键代码 一、简单介…...
【JavaScript—前端快速入门】JavaScript 对象与函数
JavaScript 对象 1. JavaScripe 数组 创建数组的方式 使用 new 关键字创建 使用字面量方式创建 [常用] 注意,JavaScipt 不要求数组元素类型都相同; 数组操作 读:使用下标的方式访问数组元素(从0开始) 保存代码,打开…...
java中的局部变量
文章目录 一、定义二、作用域和作用位置三、声明周期和初始化四、内存管理五、Java内存区域划分六、例子 一、定义 在java中,局部变量指在方法、构造方法、代码块(如{}包裹的语句块)内部声明的变量 class work {{int a 10;}public work() {i…...
【芯片设计】AI芯片前端设计工程师面试记录·20250303
【芯片前端设计面试经验专栏介绍】 专栏聚焦数字芯片前端设计核心技术与面试方法论,涵盖架构设计、RTL开发、验证方法学、低功耗设计、时序收敛等高频考点,深入解析行业头部企业的面试真题与设计场景。内容包含但不限于: 知识点系统梳理 :从Verilog/SV语法陷阱、FSM设计模式…...
(IDE接入DeepSeek)简单了解DeepSeek接入辅助开发与本地部署建议
重点:IDE接入DeepSeek是否收费 收费! 本文章主要是为了给小白避雷,目前很多文章告诉大家怎么接入DeepSeek,但是并未告知大家是否收费。如果是想白嫖的,就可以不用去接入了。 一、引言 最近爆火的AI人工智能工具DeepSe…...
【算法学习之路】5.贪心算法
贪心算法 前言一.什么是贪心算法二.例题1.合并果子2.跳跳!3. 老鼠和奶酪 前言 我会将一些常用的算法以及对应的题单给写完,形成一套完整的算法体系,以及大量的各个难度的题目,目前算法也写了几篇,题单正在更新…...
0x03 http协议和分层架构
HTTP协议 简介 Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则 http协议基于TCP协议:面向连接,安全基于请求-响应模型:一次请求对应一次响应HTTP协议是无状态的协议ÿ…...
ES批量查询
在 Elasticsearch 中,multi_search(也称为 msearch)是一种允许你在单个请求中执行多个搜索操作的 API。它可以显著减少网络开销,尤其是在需要执行多个查询时。multi_search 会将多个查询打包成一个请求发送给 Elasticsearch&#…...
React Refs:深入理解与最佳实践
React Refs:深入理解与最佳实践 引言 在React中,refs是用于访问DOM元素或组件实例的一种方式。与类组件的ref属性不同,函数组件的ref需要使用useRef钩子。正确使用refs可以大大提升React应用的性能和可维护性。本文将深入探讨React Refs的原…...
智能合约安全指南 [特殊字符]️
智能合约安全指南 🛡️ 1. 安全基础 1.1 常见漏洞类型 重入攻击整数溢出权限控制缺陷随机数漏洞前后运行攻击签名重放 1.2 安全开发原则 最小权限原则检查-生效-交互模式状态机安全失败保护机制 2. 重入攻击防护 2.1 基本防护模式 contract ReentrancyGuarde…...
【Python项目】基于Python的书籍售卖系统
【Python项目】基于Python的书籍售卖系统 技术简介:采用Python技术、MYSQL数据库等实现。 系统简介:书籍售卖系统是一个基于B/S结构的在线图书销售平台,主要分为前台和后台两部分。前台系统功能模块分为(1)用户中心模…...
【Linux】【网络】UDP打洞-->不同子网下的客户端和服务器通信(未成功版)
【Linux】【网络】UDP打洞–>不同子网下的客户端和服务器通信(未成功版) 上次说基于UDP的打洞程序改了五版一直没有成功,要写一下问题所在,但是我后续又查询了一些资料,成功实现了,这次先写一下未成功的…...
(1)udp双向通信(2)udp实现文件复制(3)udp实现聊天室
一.udp双向通信 1.fork进程实现双向通信 【1】head.h 【2】client客户端 (1)父进程从键盘获取字符串 (2)输入quit,发送结束子进程信号 (3)exit退出父进程 (1)子进程接受…...
c高级第五天
1> 在终端提示输入一个成绩,通过shell判断该成绩的等级 [90,100] : A [80, 90) : B [70, 80) : C [60, 70) : D [0, 60) : 不及格 #!/bin/bash# 提示用户输入成绩 read -p "请输入成绩(0-100):" score# 判断成…...
【JQuery—前端快速入门】JQuery 操作元素
JQuery 操作元素 1. 获取/修改元素内容 三个简单的获取元素的方法: 这三个方法即可以获取元素的内容,又可以设置元素的内容. 有参数时,就进行元素的值设置,没有参数时,就进行元素内容的获取. 接下来,我们需…...
深度学习-139-RAG技术之Agentic Chunking分块技术的工作原理及简单实现
文章目录 1 传统分块的问题2 Agentic Chunking的工作原理3 Agentic Chunking怎么实现3.1 Propositioning文本3.1.1 大语言模型3.1.2 官方提示词模板3.1.3 抽取链3.2 使用LLM Agent创建文本块3.2.1 创建新文本块3.2.2 将proposition添加到文本块3.2.3 将proposition推送到合适的…...
BambuStudio学习笔记:Flow 类
Flow 类文档 概述 Flow 类用于管理3D打印过程中的挤出流程参数计算,包括挤出宽度、间距、流量等核心参数。支持桥梁模式、不同流程角色配置,提供多种流量计算方式。 头文件 #ifndef slic3r_Flow_hpp_ #define slic3r_Flow_hpp_ // ... #endif枚举类型…...
标签的ref属性 vue中为什么不用id标记标签
标签的ref属性 vue中为什么不用id标记标签 假设有一对父子组件,如果父组件和子组件中存在id相同的标签,会产生冲突。通过id获取标签会获取到先加载那个标签。 标签的ref属性的用法 在父组件App中,引入了子组件Person。 并使用ref标记了Pe…...
7.1.1 计算机网络的组成
文章目录 物理组成功能组成工作方式完整导图 物理组成 计算机网络是将分布在不同地域的计算机组织成系统,便于相互之间资源共享、传递信息。 计算机网络的物理组成包括硬件和软件。硬件中包含主机、前端处理器、连接设备、通信线路。软件中包含协议和应用软件。 功…...
IDEA 接入 Deepseek
在本篇文章中,我们将详细介绍如何在 JetBrains IDEA 中使用 Continue 插件接入 DeepSeek,让你的 AI 编程助手更智能,提高开发效率。 一、前置准备 在开始之前,请确保你已经具备以下条件: 安装了 JetBrains IDEA&…...
mapbox基础,使用点类型geojson加载symbol符号图层,用于标注文字
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️symbol符号图层样式二、🍀使用点类型…...
