【Spring专题】Spring之Bean生命周期源码解析——阶段四(Bean销毁)(拓展,了解就好)
目录
- 前言
- 阅读建议
- 课程内容
- 一、Bean什么时候销毁
- 二、实现自定义的Bean销毁逻辑
- 2.1 实现DisposableBean或者AutoCloseable接口
- 2.2 使用@PreDestroy注解
- 2.3 其他方式(手动指定销毁方法名字)
- 三、注册销毁Bean过程及方法详解
- 3.1 AbstractBeanFactory#requiresDestruction:需要销毁吗
- 3.2 DisposableBeanAdapter.hasDestroyMethod:是否有销毁方法
- 3.3 DisposableBeanAdapter#inferDestroyMethodIfNecessary:推断销毁方法
- 3.4 AbstractBeanFactory#hasDestructionAwareBeanPostProcessors:是否有感知销毁Bean后置处理器
- 3.5 DisposableBeanAdapter.hasApplicableProcessors:是否有应用于当前Bean的销毁感知Bean后置处理器
- 3.6 DefaultSingletonBeanRegistry#registerDisposableBean:注册需要销毁的bean
- 3.7 注册销毁Bean过程总结
- 四、注册销毁Bean逻辑流程图
- 五、概念回顾
- 学习总结
前言
我们在这里讲的是Bean的销毁过程。也许,不少朋友说到Bean的销毁,可能会想到垃圾回收的东西。虽然都是在做生命周期的最后一部分,但其实这俩不是同一回事。垃圾回收是JVM级别的东西,这里说的Bean销毁是Spring的东西,所以当然不是一回事。
阅读建议
本节课的内容,将会以下面这段代码为入口讲解:
// 注册Bean的销毁接口try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;
这段代码,其实是在Spring实例化里面的AbstractAutowireCapableBeanFactory#doCreateBean()
方法里面。而且,通过这个方法名字大家也知道了,这一步仅仅只是注册销毁逻辑而已,并不是真的销毁。只有当一定条件成立的时候,才会去销毁。
registerDisposableBeanIfNecessary
具体代码如下:
/*** 将给定bean添加到此工厂中的一次性bean列表中,注册其DisposableBean接口和/或给定的destroy方法,以便在工厂关闭时调用(如果适用)。只适用于单例。 * 参数: * beanName—bean的名称—bean实例mbd—bean的bean定义 * 参见: * RootBeanDefinition。isSingleton RootBeanDefinition。getDependsOn, registerDisposableBean, registerDependentBean*/protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {if (mbd.isSingleton()) {// Register a DisposableBean implementation that performs all destruction// work for the given bean: DestructionAwareBeanPostProcessors,// DisposableBean interface, custom destroy method.registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));} else {// A bean with a custom scope...Scope scope = this.scopes.get(mbd.getScope());if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");}scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));}}}
课程内容
一、Bean什么时候销毁
Bean销毁是发生在Spring容器关闭过程中。这时,Spring所有的单例Bean都会被销毁,并且,会执行各自实现了自定义销毁逻辑的Bean的销毁方法。我们在本篇文章要介绍的,就是:如何实现自定义的Bean销毁逻辑。
在Spring容器关闭时,可以显示关闭,比如:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();// 容器关闭
context.close();
又或者,注册一个关闭钩子:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 注册关闭钩子
context.registerShutdownHook();Object newUser = context.getBean("user");
System.out.println(newUser);
【注意:强制杀掉进程(kill pid)是不会调用自定义的Bean销毁逻辑】
Spring关闭容器的过程:
- 首先发布ContextClosedEvent事件
- 调用lifecycleProcessor的onCloese()方法
- 销毁单例Bean
- 遍历disposableBeans
- 把每个disposableBean从单例池中移除
- 调用disposableBean的destroy()
- 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
- 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉
- 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanName
- 清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的beanName数组
- 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean
- 遍历disposableBeans
二、实现自定义的Bean销毁逻辑
实现方式有如下几种:
2.1 实现DisposableBean或者AutoCloseable接口
需要自定义销毁的Bean代码示例:(实现自:DisposableBean )
@Component
public class TestDestroyBean implements DisposableBean {public void test() {System.out.println("测试一下销毁方法");}@Overridepublic void destroy() throws Exception {System.out.println("TestDestroyBean------自定义的Bean销毁方法");}
}
或者:(实现自:AutoCloseable )
@Component
public class TestDestroyBean implements AutoCloseable {public void test() {System.out.println("测试一下销毁方法");}@Overridepublic void close() throws Exception {System.out.println("TestDestroyBean------自定义的Bean销毁方法");}
}
2.2 使用@PreDestroy注解
实现方式有如下3种:
@Component
public class TestDestroyBean {public void test() {System.out.println("测试一下销毁方法");}@PreDestroypublic void close() throws Exception {System.out.println("TestDestroyBean------自定义的Bean销毁方法");}
}
2.3 其他方式(手动指定销毁方法名字)
当然,还有其他方式,如:
<bean destroy-method='xxx'>
或者:
@Bean(destroyMethod = "xxx")
又或者就是,在beanDefinition
里面直接指定销毁方法:
@Component
public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (beanName.equals("user")) {beanDefinition.setInitMethodName("myInit");beanDefinition.setDestroyMethodName("xxxx");}}
}
上面说的这三种方式,有一个比较特殊的地方,因为是手动指定的,所以可以设置一个比较特殊的值:(inferred)
。
如果设置了销毁方法名字为这个,并且Bean没有实现DisposableBean
,则,在销毁的过程中,会检索bean下面有没有close
或者shutdown
方法。有,则自动绑定为【用户自定义销毁方法】。
三、注册销毁Bean过程及方法详解
本次销毁过程总过涉及了【3个核心类,6个核心方法】
3.1 AbstractBeanFactory#requiresDestruction:需要销毁吗
方法调用链:从入口:registerDisposableBeanIfNecessary()调用进来
全路径:org.springframework.beans.factory.support.AbstractBeanFactory#requiresDestruction
方法注释:将给定bean添加到此工厂中的一次性bean列表中,注册其DisposableBean接口和/或给定的destroy方法,以便在工厂关闭时调用(如果适用)。只适用于单例。
源码如下:
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessorCache().destructionAware))));
}
方法解读:里面的关键源码其实就是分两个步骤。如下:
- 是否有指定的销毁方法。
DisposableBeanAdapter.hasDestroyMethod(bean, mbd)
- 是否有
DestructionAwareBeanPostProcessor
,能感知销毁的Bean后置处理器(hasDestructionAwareBeanPostProcessors
)。有则遍历DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessorCache().destructionAware)
3.2 DisposableBeanAdapter.hasDestroyMethod:是否有销毁方法
方法调用链:由3.1中的requiresDestruction()调用过来
全路径:org.springframework.beans.factory.support.DisposableBeanAdapter#hasDestroyMethod
方法注释:检查给定bean是否有任何要调用的销毁方法。
源码如下:
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {return (bean instanceof DisposableBean || inferDestroyMethodIfNecessary(bean, beanDefinition) != null);
}
而里面的内容其实也很简单,步骤如下:
- 当前Bean是否实现了DisposableBean接口
- 没有,则调用
inferDestroyMethodIfNecessary
推断销毁方法(后面讲)
3.3 DisposableBeanAdapter#inferDestroyMethodIfNecessary:推断销毁方法
方法调用链:由3.2中的hasDestroyMethod()调用过来
全路径:org.springframework.beans.factory.support.DisposableBeanAdapter#inferDestroyMethodIfNecessary
方法注释:
如果给定beanDefinition的"destroyMethodName"属性的当前值是AbstractBeanDefinition。然后尝试推断一个销毁方法。候选方法目前仅限于名为“close”或“shutdown”的公共无参数方法(无论是在本地声明还是继承)。如果没有找到这样的方法,则将给定BeanDefinition的“destroyMethodName”更新为null,否则将设置为推断方法的名称。该常量作为@Bean#destroyMethod属性的默认值,该常量的值也可以在XML中或属性中使用。还处理java.io.Closeable和AutoCloseable接口,并在实现bean时反射地调用“close”方法。
源码如下:
@Nullableprivate static String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {String destroyMethodName = beanDefinition.resolvedDestroyMethodName;if (destroyMethodName == null) {destroyMethodName = beanDefinition.getDestroyMethodName();boolean autoCloseable = (bean instanceof AutoCloseable);if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||(destroyMethodName == null && autoCloseable)) {// 当销毁方法名字等于"(inferred)",且bean不是DisposableBean实现类destroyMethodName = null;if (!(bean instanceof DisposableBean)) {if (autoCloseable) {destroyMethodName = CLOSE_METHOD_NAME;}else {try {destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();}catch (NoSuchMethodException ex) {try {destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();}catch (NoSuchMethodException ex2) {// no candidate destroy method found}}}}}beanDefinition.resolvedDestroyMethodName = (destroyMethodName != null ? destroyMethodName : "");}return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);}
方法解读:没啥好解读的了,直接重复贴一边注释就好了。尝试推断一个销毁方法。候选方法目前仅限于名为“close”或“shutdown”的公共无参数方法(无论是在本地声明还是继承)。如果没有找到这样的方法,则将给定BeanDefinition的“destroyMethodName”更新为null,否则将设置为推断方法的名称。该常量作为@Bean#destroyMethod属性的默认值,该常量的值也可以在XML中<bean destroy-method=“”>或属性中使用。还处理java.io.Closeable和AutoCloseable接口,并在实现bean时反射地调用“close”方法。
3.4 AbstractBeanFactory#hasDestructionAwareBeanPostProcessors:是否有感知销毁Bean后置处理器
方法调用链:由3.1中的requiresDestruction()调用过来
全路径:org.springframework.beans.factory.support.AbstractBeanFactory#hasDestructionAwareBeanPostProcessors
方法注释:返回该工厂是否持有一个DestructionAwareBeanPostProcessor,该DestructionAwareBeanPostProcessor将在关闭时应用于单例bean。
源码如下:
protected boolean hasDestructionAwareBeanPostProcessors() {return !getBeanPostProcessorCache().destructionAware.isEmpty();}
3.5 DisposableBeanAdapter.hasApplicableProcessors:是否有应用于当前Bean的销毁感知Bean后置处理器
方法调用链:由3.1中的requiresDestruction()调用过来
全路径:org.springframework.beans.factory.support.DisposableBeanAdapter#hasApplicableProcessors
方法注释:检查给定bean是否有应用于它的销毁感知后处理器。
源码如下:
public static boolean hasApplicableProcessors(Object bean, List<DestructionAwareBeanPostProcessor> postProcessors) {if (!CollectionUtils.isEmpty(postProcessors)) {for (DestructionAwareBeanPostProcessor processor : postProcessors) {if (processor.requiresDestruction(bean)) {return true;}}}return false;}
经典的BeanPostProcessor处理了,不说了
3.6 DefaultSingletonBeanRegistry#registerDisposableBean:注册需要销毁的bean
方法调用链:从入口:registerDisposableBeanIfNecessary()调用进来
全路径:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerDisposableBean
方法注释:将给定的bean添加到此注册中心的销毁bean列表中。
源码如下:
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();public void registerDisposableBean(String beanName, DisposableBean bean) {synchronized (this.disposableBeans) {this.disposableBeans.put(beanName, bean);}
}
方法解读:所谓的注册,其实就是将当前bean及一些信息,添加到一个缓存map中。等到需要用到的时候,直接遍历map就好
3.7 注册销毁Bean过程总结
整体来说分为2个步骤:
- 是单例bean,判断是否需要销毁。判断步骤如下:(不同的Spring版本细节不一样,但是整体是一致的)
- 当前Bean是否实现了
DisposableBean
接口,是则直接返回true;否则进行【推断销毁方法】流程 - 推断销毁方法
- BeanDefinition中是否指定了destroyMethod,且
destroyMethod==(inferred)
。如果是,则寻找当前bean下是否有close
方法或者shutdown
方法,是则直接返回销毁方法名称 - 或者当前Bean是否实现了AutoCloseable接口,是则直接返回销毁方法名称
- BeanDefinition中是否指定了destroyMethod,且
- 如果【推断销毁方法】也没有结果,则调用【感知销毁Bean后置处理器】DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
- ApplicationListenerDetector中直接使得,如果当前bean是ApplicationListener子类需要销毁
- InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是需要销毁
- 当前Bean是否实现了
- 如果需要销毁,则适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap)
四、注册销毁Bean逻辑流程图
五、概念回顾
这里用到的一个比较重要的后置处理器是InitDestroyAnnotationBeanPostProcessor
,它的定义如下:
/***通用场景术语库beanpostprocessor实现,调用带注释的init和destroy方法。允许一个注释替代Spring的org.springframework.beans.factory.InitializingBean和org.springframework.beans.factory.DisposableBean回调接口。这个后处理器检查的实际注释类型可以通过“initAnnotationType”和“destroyAnnotationType”属性来配置。可以使用任何自定义注释,因为没有必需的注释属性。Init和destroy注释可以应用于任何可见性的方法:public、package-protected、protected或private。可以注释多个这样的方法,但建议分别只注释一个init方法和destroy方法。Spring的org.springframework.context.annotation.CommonAnnotationBeanPostProcessor支持JSR-250开箱即用的javax.annotation.PostConstruct和javax.annotation.PreDestroy注释,就像init annotation和destroy annotation一样。此外,它还支持javax.annotation.Resource注释,用于注释驱动的命名bean注入。自:2.5参见:setInitAnnotationType, setDestroyAnnotationType作者:Juergen hoel以上翻译结果来自有道神经网络翻译(YNMT)· 通用场景逐句对照*/public class InitDestroyAnnotationBeanPostProcessorimplements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
}
学习总结
- 学习了Bean销毁过程
- 学习了注册销毁Bean的逻辑
- 学习了如何自定义Bean销毁逻辑
相关文章:

【Spring专题】Spring之Bean生命周期源码解析——阶段四(Bean销毁)(拓展,了解就好)
目录 前言阅读建议 课程内容一、Bean什么时候销毁二、实现自定义的Bean销毁逻辑2.1 实现DisposableBean或者AutoCloseable接口2.2 使用PreDestroy注解2.3 其他方式(手动指定销毁方法名字) 三、注册销毁Bean过程及方法详解3.1 AbstractBeanFactory#requir…...
配置Docker,漏洞复现
目录 配置Docker 漏洞复现 配置Docker Docker的配置在Linux系统中相对简单,以下是详细步骤: 1.安装Docker:打开终端,运行以下命令以安装Docker。 sudo apt update sudo apt install docker.io 2.启动Docker服务:运…...

微信小程序 游戏水平评估系统的设计与实现_pzbe0
近年来,随着互联网的蓬勃发展,游戏公司对信息的管理提出了更高的要求。传统的管理方式已无法满足现代人们的需求。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,随着各行业的不断发展,使命召…...
moba登录不进去提示修改问题问题解决方式
问题: 安装moba后,运行时运行不起来,提示输入密码,安装、卸载多个版本都不行 方法: 使用ResetMasterPassword工具进行重置主密码 官网下载地址: MobaXterm Xserver and tabbed SSH client - resetmaster…...

Unsafe upfileupload
文章目录 client checkMIME Typegetimagesize 文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像、上传附件等等。当用户点击上传按钮后,后台会对上传的文件进行判断 比如是否是指定的类型、后缀名、大小等等,然后将其按…...

机器人制作开源方案 | 滑板助力器
我们可以用一块废滑板做些什么呢? 如今,越来越多的人选择电动滑板作为代步工具或娱乐方式,市场上也涌现出越来越多的电动滑板产品。 (图片来源:Backfire Zealot X Belt Drive Electric Skateboard– Backfire Board…...

飞机打方块(二)游戏界面制作
一、背景 1.新建bg节点 二、飞机节点功能实现 1.移动 1.新建plane节点 2.新建脚本GameController.ts,并绑定Canvas GameControll.ts const { ccclass, property } cc._decorator;ccclass export default class NewClass extends cc.Component {property(cc.Node)canvas:…...
自我理解:精度(precision)和召回(recall)
1、精度(precision) 精度是用于评估分类模型的一个重要指标。它反映了模型预测为正例的样本中,实际真正为正例样本的比例。 【注】正例样本指在二分类问题中,被标注为正类的样本。 例如:在垃圾邮件分类任务中,正例样本就是真实的…...
Nginx 使用 HTTPS(准备证书和私钥)
文章目录 Nginx生成自签名证书和配置Nginx HTTPS(准备证书和私钥)准备证书和私钥 Nginx生成自签名证书和配置Nginx HTTPS(准备证书和私钥) 准备证书和私钥 生成私钥 openssl genrsa -des3 -out server.key 2048这会生成一个加密…...

Java:集合框架:Set集合、LinkedSet集合、TreeSet集合、哈希值、HashSet的底层原理
Set集合 创建一个Set集合对象,因为Set是一个接口不能直接new一个对象,所以要用一个实现类来接 HashSet来接 无序性只有一次,只要第一次运行出来后,之后再运行的顺序还是第一次的顺序。 用LinkedSet来接 有序 不重复 无索引 用Tree…...
自定义Taro的navBar的宽度和高度
本方法是计算自定义navbar的宽度和高度,输出的参数有 navBarHeight, menuBottom,menuHeight, menuRectWidth,windowWidth, windowHeight,具体代码如下: export function getCustomNavBarRect():| {navBarHeight: number;menuBottom: number;menuHeight:…...
用Python编程实现百度自然语言处理接口的对接,助力你开发智能化处理程序
用Python编程实现百度自然语言处理接口的对接,助力你开发智能化处理程序 随着人工智能的不断进步,自然语言处理(Natural Language Processing,NLP)成为了解决文本处理问题的重要工具。百度自然语言处理接口提供了一系…...

系统架构设计专业技能 · 系统工程与系统性能
系列文章目录 系统架构设计专业技能 网络技术(三) 系统架构设计专业技能 系统安全分析与设计(四)【系统架构设计师】 系统架构设计高级技能 软件架构设计(一)【系统架构设计师】 系统架构设计高级技能 …...

初识网络原理(笔记)
目录 编辑局域网 网络通信基础 IP 地址 端口号 协议 协议分层 TCP / IP 五层网络模型 网络数据传输的基本流程 发送方的情况: 接收方的情况 局域网 搭建网络的时候,需要用到 交换机 和 路由器 路由器上,有 lan 口 和 wan 口 虽…...

嵌入式C语言基本操作方法之经典
C语言一经出现就以其功能丰富、表达能力强、灵活方便、应用面广等特点迅速在全世界普及和推广。 C语言不但执行效率高而且可移植性好,可以用来开发应用软件、驱动、操作系统等。 C语言也是其它众多高级语言的鼻祖语言,所以说学习C语言是进入编程世界的必…...
postgresql \watch实用的使用方法
文章目录 1.介绍2.语法3.实用的使用方法3.1 慢sql监控3.2 长wait事件3.3 日志输出量3.3结合pg_stat_database使用3.4 结合pg_stat_bgwriter使用3.5 其他 1.介绍 \watch Postgres 9.3 版带来的一个有用的命令,与linux watch指令类似,可以帮我们在指定间隔…...
Cocos2d 项目问题记录
环境搭建 正常运行 Android 端的 Cocos2d 项目,本机至少需要 Android SDK、NDK 环境、Android Studio 项目报错总结 CMake Error: CMake was unable to find a build program corresponding to "Ninja" 默认创建工程的 gradle.tools 版本为 3.1.0&…...

系统架构合理性的思考 | 京东云技术团队
最近牵头在梳理部门的系统架构合理性,开始工作之前,我首先想到的是如何定义架构合理性? 从研发的角度来看如果系统上下文清晰、应用架构设计简单、应用拆分合理应该称之为架构合理。 基于以上的定义可以从以下三个方面来梳理评估࿱…...

Amelia预订插件:WordPress企业级预约系统
并非所有WordPress预订插件都像他们所设计的那样。其中一些缺乏运行高效预约操作所需的功能,而其他一些则看起来陈旧过时。您不需要其中任何一个,但Amelia预订插件似乎希望确保所有用户都对功能和风格感到满意。 在这篇Amelia企业级预约系统插件评测中&…...
共享门店模式:线下门店的商家如何利用它增加客户
随着数字化时代的到来,商业模式正在不断创新与演变,而共享经济正成为引领这一变革的重要力量。在这个大背景下,共享门店模式作为共享经济的一种体现,正在逐渐走进人们的生活,并为商家和消费者带来了新的商机和体验。 共…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...