Spring boot启动原理及相关组件
优质博文IT-BLOG-CN一、Spring Boot应用启动一个Spring Boot应用的启动通常如下SpringBootApplication Slf4j public class ApplicationMain { public static void main(String[] args) { ConfigurableApplicationContext ctx SpringApplication.run(ApplicationMain.class, args); } }执行如上代码Spring Boot程序启动成功。事实上启动Spring Boot应用离不开SpringApplication。所以我们跟随SpringApplication的脚步开始从源码角度分析Spring Boot的初始化过程。btw可参看例子一节我对Spring Boot启动的拓展点都做了demo可参照下面源码分析进行理解。文档有一句话说了SpringApplication做了什么目的Create an appropriate ApplicationContext instance (depending on your classpath) Register a CommandLinePropertySource to expose command line arguments as Spring properties Refresh the application context, loading all singleton beans Trigger any CommandLineRunner beans二、SpringApplication构造函数启动代码先创建SpringApplication示例在执行run方法public static ConfigurableApplicationContext run(Class?[] primarySources, String[] args) { return new SpringApplication(primarySources).run(args); }如下是SpringApplication的构造函数代码分析。this.resourceLoader resourceLoader; Assert.notNull(primarySources, PrimarySources must not be null); this.primarySources new LinkedHashSet(Arrays.asList(primarySources)); //通过Classloader探测不同web应用核心类是否存在进而设置web应用类型 this.webApplicationType WebApplicationType.deduceFromClasspath(); //找出所有spring.factories中声明的ApplicationContextInitializer并设置 //ApplicationContextInitializer定义了回调接口在refresh()前初始化调用即在prepareContext的applyInitializers方法中调用 setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); //找出所有spring.factories中声明的ApplicationListener细节往后再叙ApplicationListener继承了 //java.util.EventListener实现了类似观察者模式的形式通过实现ApplicationListener、SmartApplicationListener能够监听Spring上下文的refresh、Prepared等事件或者是自定义事件 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); //找出主启动类有趣的是是通过new一个runtime异常然后在异常栈里面找出来的 this.mainApplicationClass deduceMainApplicationClass();在构造期间主要做了1、判定应用类型为后面创建不同类型的spring context做准备。2、初始化ApplicationContextInitializer和ApplicationListener。3、找出启动类。三、run()源码解析介绍run()方法前先说说贯穿run方法的ApplicationRunListener它有助于理解整个run()的运行周期。写在这里Spring Application事件机制run()方法分析如下//java.awt.headless是J2SE的一种模式用于在缺失显示屏、鼠标或者键盘时的系统配置。 configureHeadlessProperty(); //将spring.factories中的SpringApplicationRunListener接口实现类拖出来塞到SpringApplicationRunListeners一个集合中统一批量执行 SpringApplicationRunListeners listeners getRunListeners(args); //触发runlistener的starting listeners.starting(); try { ApplicationArguments applicationArguments new DefaultApplicationArguments( args); ConfigurableEnvironment environment prepareEnvironment(listeners, applicationArguments); //spring.beaninfo.ignore如果没有设置值则把它设为true具体情况具体设置 //如果没用的话把它设为true可以ignore掉classloader对于不存在的BeanInfo的扫描提高性能。 configureIgnoreBeanInfo(environment); //banner打印。自定义banner挺好玩的 Banner printedBanner printBanner(environment); //根据webApplicationType一开始推断的应用类型去新建applicationContext context createApplicationContext(); //获取SpringBootExceptionReporter回调接口类提供启动时的异常报告 exceptionReporters getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); //下面会说 prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); //do nothing afterRefresh(context, applicationArguments); //计时停止 stopWatch.stop(); //打日志 if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } //启动 listeners.started(context); //找出context的ApplicationRunner和CommandLineRunner用AnnotationAwareOrderComparator排序并执行 callRunners(context, applicationArguments);下面再分别说说两个方法prepareEnvironment、refreshContext的代码。四、prepareEnvironmentprivate ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { // Create and configure the environment ConfigurableEnvironment environment getOrCreateEnvironment(); configureEnvironment(environment, applicationArguments.getSourceArgs()); //发布environment prepared事件 listeners.environmentPrepared(environment); //将获取到的environment中的spring.main配置绑定到SpringApplication中, //使用的是Binder这个spring boot2.0开始有的类 bindToSpringApplication(environment); if (!this.isCustomEnvironment) { environment new EnvironmentConverter(getClassLoader()) .convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); } //附加的解析器将动态跟踪底层 Environment 属性源的任何添加或删除 //关于ConfigurationPropertySourcesPropertySource和MutablePropertiySource //将在Environment中作进一步讲解 ConfigurationPropertySources.attach(environment); return environment; }五、prepareContextprivate void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //为上下文设置environment配置、profile context.setEnvironment(environment); //对application做一些处理设置一些组件 //比如BeanNameGeneratorApplicationConversionService包含一些默认的Converter和formatter postProcessApplicationContext(context); // 加载并运行ApplicationContextInitializer applyInitializers(context); listeners.contextPrepared(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 DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } // Load the sources SetObject sources getAllSources(); Assert.notEmpty(sources, Sources must not be empty); //Load beans其实是由sources构建beanDefinition into the application context. //构建BeanDefinitionLoader并执行BeanDefinitionLoader.load() load(context, sources.toArray(new Object[0])); //执行contextLoaded事件 listeners.contextLoaded(context); }六、容器refreshrefreshContextprivate void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } }refreshContext会做两件事1、应用上下文刷新2、注册shutdown钩子我们来看看ServletWebServer的刷新。// ServletWebServerApplicationContext public final void refresh() throws BeansException, IllegalStateException { try { super.refresh(); } catch (RuntimeException ex) { //停止webserver stopAndReleaseWebServer(); throw ex; } } org.springframework.context.support.AbstractApplicationContext refresh() public void refresh() throws BeansException, IllegalStateException { // 单线程执行 synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 1、设置Spring容器的启动时间撤销关闭状态开启活跃状态。2、初始化属性源信息(Property)3、验证环境信息里一些必须存在的属性 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // 如果是RefreshtableApplicationContext会做了很多事情 // 1、让子类刷新内部beanFactory 创建IoC容器DefaultListableBeanFactory--ConfigurableListableBeanFactory 的实现类 // 2、加载解析XML文件最终存储到Document对象中 // 3、读取Document对象并完成BeanDefinition的加载和注册工作 ConfigurableListableBeanFactory beanFactory obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //从Spring容器获取BeanFactory(Spring Bean容器)并进行相关的设置为后续的使用做准备 //1、设置classloader(用于加载bean)设置表达式解析器(解析bean定义中的一些表达式)添加属性编辑注册器(注册属性编辑器) //2、添加ApplicationContextAwareProcessor这个BeanPostProcessor。取消ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、EnvironmentAware这5个接口的自动注入。因为ApplicationContextAwareProcessor把这5个接口的实现工作做了 //3、设置特殊的类型对应的bean。BeanFactory对应刚刚获取的BeanFactoryResourceLoader、ApplicationEventPublisher、ApplicationContext这3个接口对应的bean都设置为当前的Spring容器 //4、注入一些其它信息的bean比如environment、systemProperties等 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. 执行beanfactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注册beanPostProcessor registerBeanPostProcessors(beanFactory); // Initialize message source for this context. 初始化messageSource 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 Springs core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }七、postProcessBeanFactory()设置BeanFactory之后再进行后续的一些BeanFactory操作。不同的Context会进行不同的操作。 比如AnnotationConfigServletWebServerApplicationContextprotected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 父类实现会注册web应用特有的factory scope super.postProcessBeanFactory(beanFactory); //查看basePackages属性如果设置了会使用ClassPathBeanDefinitionScanner去扫描basePackages包下的bean并注 if (this.basePackages ! null this.basePackages.length 0) { this.scanner.scan(this.basePackages); } // 查看annotatedClasses属性如果设置了会使用AnnotatedBeanDefinitionReader去注册这些bean if (!this.annotatedClasses.isEmpty()) { this.reader.register(ClassUtils.toClassArray(this.annotatedClasses)); } }八、invokeBeanFactoryPostProcessors()/** * Instantiate and invoke all registered BeanFactoryPostProcessor beans, * respecting explicit order if given. * pMust be called before singleton instantiation. */ protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { //执行AbstractContext持有的BeanFactory后置处理器 //这些处理器是之前ContextInitializer PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an Bean method registered by ConfigurationClassPostProcessor) // 如果通过-javaagent参数设置了LTW的织入器类包那么增加LTW的BeanProcessor。 if (beanFactory.getTempClassLoader() null beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }从容器中找出BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor二者的区别是一个使用BeanDefinitionRegistry作处理一个使用BeanFactory做处理 并按一定的规则顺序执行。ConfigurationClassPostProcessor的优先级为最高它会对项目中的Configuration注解修饰的类(Component、ComponentScan、Import、ImportResource修饰的类也会被处理)进行解析解析完成之后把这些bean注册到BeanFactory中。 需要注意的是这个时候注册进来的bean还没有实例化。ConfigurationClassPostProcessor的流程之后会独立进行分析。九、registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)方法···java/**Instantiate and invoke all registered BeanPostProcessor beans,respecting explicit order if given.Must be called before any instantiation of application beans.*/protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {//委派PostProcessorRegistrationDelegate去做PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);}从Spring容器中按一定顺序PriorityOrdered、Ordered、非PriorityOrdered非Ordered找出实现了BeanPostProcessor接口的bean并设置到BeanFactory的属性中。之后bean被实例化的时候会调用这个BeanPostProcessor。 ## 十、initMessageSource() 初始化一些国际化相关的属性。 Spring boot的国际化配置可阅读MessageSourceAutoConfiguration。 默认情况会设置一个DelegatingMessageSource是一个空实现因为ApplicationContext接口拓展了MessageSource接口所以Spring容器都有getMessage方法 可是在实现上又允许空MessageSource所以通过一个DelegatingMessageSource去适配。 ## 十一、initApplicationEventMulticaster() Initialize event multicaster for this context. 初始化事件广播器。默认实现是SimpleApplicationEventMulticaster。 onRefresh() 模板方法给不同的Spring应用容器去实例化一些特殊的类。 比如AnnotationConfigServletWebServerApplicationContext、AnnotationConfigReactiveWebServerApplicationContext会去创建web servercreateWebServer()。 spring boot的mvc内置支持有tomcat、Undertow、jetty三种server而reactive web server则内置支持tomcat、jetty、netty三种。 java // Unlike Jetty, all Tomcat threads are daemon threads. We create a // blocking non-daemon to stop immediate shutdown startDaemonAwaitThread();btw如果是tomcat server的话spring boot会启动多一个线程防止退出。十二、registerListeners()把BeanFactory的ApplicationListener拿出来塞到事件广播器里。如果ApplicationContext的earlyApplicationEvents属性有值则广播该属性持有的early事件。十三、finishBeanFactoryInitialization(beanFactory)实例化BeanFactory中已经被注册但是未实例化的所有实例(懒加载的不需要实例化)。比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类在这个时候都会被初始化。十四、finishRefresh()// ReactiveWebServerApplicationContext Override protected void finishRefresh() { super.finishRefresh(); WebServer webServer startReactiveWebServer(); if (webServer ! null) { publishEvent(new ReactiveWebServerInitializedEvent(webServer, this)); } } // AbstractApplicationContext /** * Finish the refresh of this context, invoking the LifecycleProcessors * onRefresh() method and publishing the * {link org.springframework.context.event.ContextRefreshedEvent}. */ protected void finishRefresh() { // Clear context-level resource caches (such as ASM metadata from scanning). // 容器完成刷新清除资源缓存 clearResourceCaches(); // Initialize lifecycle processor for this context. // 初始化lifeCycleProcessor, 默认实现是DefaultLifeCycleProcessor实现了BeanFactoryAware接口通过BeanFactory找出LifeCycle bean // 可通过自定义实现LifeCycle接口的Bean来监听容器的生命周期。 initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. //粗发生命周期处理器的onRefresh方法顺带一说在程序正常退出时会粗发shutdownHook那时会粗发生命周期处理器的onClose方法 getLifecycleProcessor().onRefresh(); // Publish the final event. // 广播ContextRefreshed事件 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. // 将ApplicationContext注册到Spring tool suite里 LiveBeansView.registerApplicationContext(this); }十五、resetCommonCaches()// Reset common introspection caches in Springs core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches();最后会在finally执行resetCommonCaches()清除一些Spring core、beans加载和解析的Bean信息缓存因为对于singleton bean来说已经不需要了。十六、流程整理最后按照启动阶段整理一幅全景图。十七、例子在github里我把Spring Boot应用启动的拓展组件自定义的应用初始器、监听器、事件、ApplicationRunner都写了例子可参照阅读。 代码在这 | spring-boot-none-startup日志如下2020-05-20 18:30:11.625 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.r.SimpleRunListener : environmentPrepared, env:StandardEnvironment {activeProfiles[dev], defaultProfiles[default], propertySources[MapPropertySource {namesystemProperties}, OriginAwareSystemEnvironmentPropertySource {namesystemEnvironment}, RandomValuePropertySource {namerandom}, OriginTrackedMapPropertySource {nameapplicationConfig: [classpath:/application-dev.yml]}, OriginTrackedMapPropertySource {nameapplicationConfig: [classpath:/application.yml]}]} . ____ _ __ _ _ /\ / ____ __ _ _(_)_ __ __ _( ( )___ | _ | | | ’/ |/)| |)| | | | | || (| | ) ) ) )’ || .__|| ||| |, | / / / /|||////_/:: Spring Boot :: (v2.1.3.RELEASE)2020-05-20 18:30:11.832 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.r.SimpleRunListener : contextPrepared, ctx:org.springframework.context.annotation.AnnotationConfigApplicationContext1d730606, started on Thu May 01 08:00:00 CST 1970 2020-05-20 18:30:11.838 INFO 81568 --- [ main] n.t.d.s.b.startup.none.ApplicationMain : Starting ApplicationMain on DESKTOP-OLDGHC1 with PID 81568 ( started by teash in ) 2020-05-20 18:30:11.838 INFO 81568 --- [ main] n.t.d.s.b.startup.none.ApplicationMain : The following profiles are active: dev 2020-05-20 18:30:11.894 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.r.SimpleRunListener : contextLoaded, context: org.springframework.context.annotation.AnnotationConfigApplicationContext1d730606, started on Thu May 01 08:00:00 CST 1970 2020-05-20 18:30:12.404 INFO 81568 --- [ main] .s.b.s.n.s.SimpleApplicationContextAware : SimpleApplicationContextAware and send SimpleAppEvent 2020-05-20 18:30:12.441 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.e.SimpleEventListener : event: net.teaho.demo.spring.boot.startup.none.spring.event.SimpleAppEvent[sourceevent source], source: event source 2020-05-20 18:30:12.444 INFO 81568 --- [ main] n.t.d.s.b.s.n.config.BeanConfiguration : [net.teaho.demo.spring.boot.startup.none.spring.spi.DemoSpringLoaderImplc96a4ea] 2020-05-20 18:30:12.484 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.l.LoggingLifeCycle : In Life cycle bean start(). 2020-05-20 18:30:12.496 INFO 81568 --- [ main] n.t.d.s.b.startup.none.ApplicationMain : Started ApplicationMain in 1.573 seconds (JVM running for 3.195) 2020-05-20 18:30:12.496 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.r.SimpleRunListener : started, context: org.springframework.context.annotation.AnnotationConfigApplicationContext1d730606, started on Mon May 25 18:30:11 CST 2020 2020-05-20 18:30:12.497 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.r.EchoApplicationRunner : EchoApplicationRunner running, args:org.springframework.boot.DefaultApplicationArguments45673f68 2020-05-20 18:30:12.497 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.r.EchoCommandLineRunner : EchoCommandLineRunner running 2020-05-20 18:30:12.497 INFO 81568 --- [ main] n.t.d.s.b.s.n.s.r.SimpleRunListener : running, context: org.springframework.context.annotation.AnnotationConfigApplicationContext1d730606, started on Mon May 25 18:30:11 CST 2020 2020-05-20 18:30:12.500 INFO 81568 --- [ Thread-3] n.t.d.s.b.s.n.s.l.LoggingLifeCycle : In Life cycle bean stop().

相关新闻

Flutter 三方库 pubspec_yaml 的鸿蒙化适配指南 - 掌控配置元数据资产、YAML 治理实战、鸿蒙级精密定义专家

Flutter 三方库 pubspec_yaml 的鸿蒙化适配指南 - 掌控配置元数据资产、YAML 治理实战、鸿蒙级精密定义专家

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net Flutter 三方库 pubspec_yaml 的鸿蒙化适配指南 - 掌控配置元数据资产、YAML 治理实战、鸿蒙级精密定义专家 在鸿蒙跨平台应用执行高级配置管理与多维 YAML 资产指控(如构建一个…

2026/7/3 6:49:25 阅读更多 →
自动生成接口:XinServer 是如何让接口开发变得不需要代码的

自动生成接口:XinServer 是如何让接口开发变得不需要代码的

自动生成接口:XinServer 是如何让接口开发变得不需要代码的 兄弟们,不知道你们有没有过这种经历:产品经理或者甲方爸爸又提新需求了,要加个用户积分系统,或者搞个活动报名功能。你作为前端或者移动端开发,心…

2026/5/17 9:32:16 阅读更多 →
Spring Boot实现多数据源连接和切换

Spring Boot实现多数据源连接和切换

文章目录 前言一、多数据源配置与切换方案二、实现步骤 1. 创建多个 DataSource 配置类2. 创建 DataSource 配置类3. 创建动态数据源路由类4. 实现 DynamicDataSource 类5. 创建 DataSourceContextHolder 来存储当前的数据源标识6. AOP 方式切换数据源7. 自定义注解来指定数据…

2026/5/17 9:32:15 阅读更多 →

最新新闻

SweetModal-Vue 高级用法:实现复杂交互弹窗的终极教程

SweetModal-Vue 高级用法:实现复杂交互弹窗的终极教程

SweetModal-Vue 高级用法:实现复杂交互弹窗的终极教程 【免费下载链接】sweet-modal-vue The sweetest library to happen to modals. 项目地址: https://gitcode.com/gh_mirrors/sw/sweet-modal-vue SweetModal-Vue 是一个功能强大的 Vue.js 弹窗组件库&…

2026/7/4 7:25:02 阅读更多 →
HPL1Engine渲染管线解析:从2D到3D图形的高效处理方案

HPL1Engine渲染管线解析:从2D到3D图形的高效处理方案

HPL1Engine渲染管线解析:从2D到3D图形的高效处理方案 【免费下载链接】HPL1Engine A real time 3D engine. 项目地址: https://gitcode.com/gh_mirrors/hp/HPL1Engine HPL1Engine是一款功能强大的实时3D引擎,其渲染管线设计实现了从2D到3D图形的高…

2026/7/4 7:25:02 阅读更多 →
KVAE-Audio在音频修复中的应用:如何提升损坏音频质量

KVAE-Audio在音频修复中的应用:如何提升损坏音频质量

KVAE-Audio在音频修复中的应用:如何提升损坏音频质量 【免费下载链接】KVAE-Audio 项目地址: https://ai.gitcode.com/hf_mirrors/kandinskylab/KVAE-Audio KVAE-Audio是一款连续全频段(48 kHz)音频自动编码器,能够将原始…

2026/7/4 7:23:02 阅读更多 →
Windows Research Kernel (WRK) 实战案例:如何通过修改内核实现自定义系统调用

Windows Research Kernel (WRK) 实战案例:如何通过修改内核实现自定义系统调用

Windows Research Kernel (WRK) 实战案例:如何通过修改内核实现自定义系统调用 【免费下载链接】Windows-Research-Kernel-WRK- Windows Research Kernel Source Code 项目地址: https://gitcode.com/gh_mirrors/wi/Windows-Research-Kernel-WRK- Windows Re…

2026/7/4 7:23:02 阅读更多 →
CMS备份与恢复:Instatic完整灾难恢复演练

CMS备份与恢复:Instatic完整灾难恢复演练

CMS备份与恢复:Instatic完整灾难恢复演练 【免费下载链接】Instatic Instatic is a modern self-hosted visual CMS - get it running in 1 minute 项目地址: https://gitcode.com/GitHub_Trending/in/Instatic Instatic作为一款现代化自托管视觉CMS&#xf…

2026/7/4 7:21:01 阅读更多 →
status-go终极指南:构建去中心化社交应用的完整Go后端解决方案

status-go终极指南:构建去中心化社交应用的完整Go后端解决方案

status-go终极指南:构建去中心化社交应用的完整Go后端解决方案 【免费下载链接】status-go The "backend" library for Status Apps 项目地址: https://gitcode.com/gh_mirrors/st/status-go 想要快速构建去中心化社交应用?&#x1f68…

2026/7/4 7:16:59 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻