当前位置: 首页 > news >正文

Spring Bean 的生命周期详解

所谓万物皆对象,对于一个 bean 而言,从出生到死亡,他要经历哪些阶段呢?

生命周期

理解对象的生命周期,可以帮助我们更好的做一些扩展。

在这里插入图片描述

一个对象从被创建到被垃圾回收,可以大致分为这 5 个阶段:

  1. 创建/实例化阶段:调用类的构造方法,产生一个新对象;
  2. 初始化阶段:此时对象已经被创建了,但还未被正常使用,可以在这里做一些初始化的操作;
  3. 运行使用期:此时对象已经完全初始化好,程序正常运行,对象被使用;
  4. 销毁阶段:此时对象准备被销毁,需要预先的把自身占用的资源等处理好(如关闭、释放数据库连接);
  5. 回收阶段:此时对象已经完全没有被引用了,被垃圾回收器回收。

理解了一个 Bean 的生命周期后,下面我们看下SpringFramework怎么对Bean 的生命周期做干预的。

单实例 Bean 的生命周期

init-method & destroy-method

1)创建 Bean

package com.study.spring.a_initmethod;public class Cat {private String name;public Cat() {System.out.println("Cat 构造方法执行了。。。");}public void setName(String name) {System.out.println("setName方法执行了。。。");this.name = name;}public void init() {System.out.println(name + " 被初始化了。。。");}public void destroy() {System.out.println(name + " 被销毁了。。。");}
}public class Dog {private String name;public Dog() {System.out.println("Dog 构造方法执行了。。。");}public void setName(String name) {System.out.println("setName方法执行了。。。");this.name = name;}public void init() {System.out.println(name + "被初始化了。。。");}public void destroy() {System.out.println(name + "被销毁了。。。");}
}

2)分别创建 XML 文件 和 注解配置类

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.study.spring.a_initmethod.Cat" init-method="init" destroy-method="destroy"><property name="name" value="小米米"/></bean>
</beans>
@Configuration
public class Config {@Bean(initMethod = "init",destroyMethod = "destroy")public Dog dog(){Dog dog = new Dog();dog.setName("小勾勾");return dog;}
}

3)分别测试xml 和注解驱动

private static void testXml() {System.out.println("准备初始化IOC容器。。。");ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-initmethod.xml");System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");context.close();System.out.println("IOC容器销毁完成。。。");}private static void testAnnotationConfig() {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");applicationContext.close();System.out.println("IOC容器销毁完成。。。");}

输出如下:

准备初始化IOC容器。。。
Cat 构造方法执行了。。。
setName方法执行了。。。
小米米 被初始化了。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
小米米 被销毁了。。。
IOC容器销毁完成。。。-----------------------------准备初始化IOC容器。。。
Dog 构造方法执行了。。。
setName方法执行了。。。
小勾勾被初始化了。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
小勾勾被销毁了。。。
IOC容器销毁完成。。。

由此可以得出结论:在 IOC 容器初始化之前,默认情况下 Bean 已经创建好了,而且完成了初始化动作;容器调用销毁动作时,先销毁所有 Bean ,最后 IOC 容器全部销毁完成。

同时也可以看出来,在 Bean 的生命周期中,是先对属性赋值,后执行 init-method 标记的方法。

@PostConstruct & @PreDestroy

上面的 Cat 和 Dog 都是我们手动声明注册的,但是对于那些使用模式注解的 Bean ,这种方式就不好使了,因为没有可以声明 init-methoddestroy-method 的地方了。

此时可以使用JSR250 规范提供的 @PostConstruct@PreDestroy 这两个注解,分别对应 init-methoddestroy-method

比如,Spring中常用的模式注解:@Component、@Service、@Repository、@Controller,使用这些注解,Spring容器可以在启动时自动扫描并注册这些Bean,而不需要显式地在XML配置文件中声明或在Java配置类中手动注册。

1)创建Bean

@Component
public class Pen {private Integer ink;public Pen(){System.out.println("钢笔的构造方法");}@PostConstructpublic void addInk() {System.out.println("钢笔中已加满墨水。。。");this.ink = 100;}@PreDestroypublic void outWellInk() {System.out.println("钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}
}

2)测试

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.study.spring.b_jsr250");System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");ctx.close();System.out.println("IOC容器销毁完成。。。");}
}

输出如下:

准备初始化IOC容器。。。
钢笔的构造方法
钢笔中已加满墨水。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
钢笔中的墨水都放干净了。。。
IOC容器销毁完成。。。

可以得出结论:这两个注解实现的效果和 init-methoddestroy-method 是一样的。

JSR250规范 与 init-method 共存

如果 @PostConstruct@PreDestroyinit-methoddestroy-method 共存,执行顺序是怎样的呢?

1)创建 Bean

public class Pen {private Integer ink;public Pen(){System.out.println("钢笔的构造方法");}public void open() {System.out.println("init method ...打开钢笔");}public void close() {System.out.println("destroy-method - 合上钢笔。。。");}@PostConstructpublic void addInk() {System.out.println("@PostConstruct...钢笔中已加满墨水。。。");this.ink = 100;}@PreDestroypublic void outWellInk() {System.out.println("@PreDestroy...钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}
}

2)创建配置类

@Configuration
public class JSR250Configuration {@Bean(initMethod = "open",destroyMethod = "close")public Pen pen() {return new Pen();}
}

3)测试执行

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(JSR250Configuration.class);System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");applicationContext.close();System.out.println("IOC容器销毁完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
钢笔的构造方法
@PostConstruct...钢笔中已加满墨水。。。
init method ...打开钢笔
IOC容器初始化完成。。。准备销毁IOC容器。。。
@PreDestroy...钢笔中的墨水都放干净了。。。
destroy-method - 合上钢笔。。。
IOC容器销毁完成。。。

可以得出结论:JSR250 规范的执行优先级高于 init / destroy。

InitializingBean & DisposableBean

是 SpringFramework 内部预先定义好的两个关于生命周期的接口,他们的触发时机与 init-method & destroy-method@PostConstruct @PreDestroy一样,都是在 Bean 的初始化和销毁阶段要回调的。

1)创建 Bean

@Component
public class Pen implements InitializingBean, DisposableBean {private Integer ink;@Overridepublic void destroy() throws Exception {System.out.println("钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("钢笔中已加满墨水。。。");this.ink = 100;}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}
}

2)测试执行

public class InitializingDisposableAnnoApplication {public static void main(String[] args) throws Exception {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.study.spring.c_initializingbean");System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");ctx.close();System.out.println("IOC容器销毁完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
钢笔中已加满墨水。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
钢笔中的墨水都放干净了。。。
IOC容器销毁完成。。。

三种生命周期并存

当一个 Bean 同时用这三种生命周期控制时,执行顺序又是怎么样的呢?

1)创建 Bean

@Component
public class Pen implements InitializingBean, DisposableBean {private Integer ink;public Pen(){System.out.println("构造方法");}public void open() {System.out.println("init-method - 打开钢笔。。。");}public void close() {System.out.println("destroy-method - 合上钢笔。。。");}@PostConstructpublic void addInk() {System.out.println("@PostConstruct 钢笔中已加满墨水。。。");this.ink = 100;}@PreDestroypublic void outwellInk() {System.out.println("@PreDestroy 钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic void destroy() throws Exception {System.out.println("DisposableBean - 写完字了。。。");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean - 准备写字。。。");}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}}

2)创建配置类

@Configuration
public class Config {@Bean(initMethod = "open",destroyMethod = "close")public Pen pen(){return new Pen();}
}

3)测试执行

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");ctx.close();System.out.println("IOC容器销毁完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
构造方法
@PostConstruct 钢笔中已加满墨水。。。
InitializingBean - 准备写字。。。
init-method - 打开钢笔。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
@PreDestroy 钢笔中的墨水都放干净了。。。
DisposableBean - 写完字了。。。
destroy-method - 合上钢笔。。。
IOC容器销毁完成。。。

可以看到执行顺序是:@PostConstruct → InitializingBean → init-method

原型Bean的生命周期

当面介绍的都是单实例 Bean 的生命周期,而对于原型 Bean,它与单实例 Bean 的生命周期是不一样的。

单实例 Bean 的生命周期是陪着 IOC 容器一起的,容器初始化,单实例 Bean 也跟着初始化(延迟 Bean 例外);
容器销毁,单实例 Bean 也跟着销毁。
原型 Bean 由于每次都是取的时候才产生一个,所以它的生命周期与 IOC 容器无关。

1)创建 Bean

@Component
public class Pen implements InitializingBean, DisposableBean {private Integer ink;public Pen(){System.out.println("构造方法");}public void open() {System.out.println("init-method - 打开钢笔。。。");}public void close() {System.out.println("destroy-method - 合上钢笔。。。");}@PostConstructpublic void addInk() {System.out.println("@PostConstruct 钢笔中已加满墨水。。。");this.ink = 100;}@PreDestroypublic void outWellInk() {System.out.println("@PreDestroy 钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean - 准备写字。。。");}@Overridepublic void destroy() throws Exception {System.out.println("DisposableBean - 写完字了。。。");}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}
}

2)创建配置类

@Configuration
public class Config {@Bean(initMethod = "open",destroyMethod = "close")@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) //原型Beanpublic Pen pen(){return new Pen();}
}

3)测试执行

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
IOC容器初始化完成。。。

由此得出结论:原型 Bean 的创建不随 IOC 的初始化而创建。

然后,在main 方法中去获取该 Bean,再次执行:

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");System.out.println("准备获取pen");Pen pen = ctx.getBean(Pen.class);System.out.println("获取到pen");}
}

输出结果:

准备初始化IOC容器。。。
IOC容器初始化完成。。。
准备获取pen
构造方法
@PostConstruct 钢笔中已加满墨水。。。
InitializingBean - 准备写字。。。
init-method - 打开钢笔。。。
获取到pen

由此得出结论:原型Bean的初始化动作与单实例Bean完全一致。

接着,我们把销毁 Bean 的代码也加上:

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");System.out.println("准备获取pen");Pen pen = ctx.getBean(Pen.class);System.out.println("获取到pen");System.out.println("用完Pen了,准备销毁。。。");ctx.getBeanFactory().destroyBean(pen);System.out.println("Pen销毁完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
IOC容器初始化完成。。。
准备获取pen
构造方法
@PostConstruct 钢笔中已加满墨水。。。
InitializingBean - 准备写字。。。
init-method - 打开钢笔。。。
获取到pen
用完Pen了,准备销毁。。。
@PreDestroy 钢笔中的墨水都放干净了。。。
DisposableBean - 写完字了。。。
Pen销毁完成。。。

由此得出结论;原型 Bean 在销毁时不处理 destroyMethod 标注的方法


后置处理器 BeanPostProcessor

BeanPostProcessor 是一个容器的扩展点,它可以在 bean 的生命周期过程中,初始化阶段前后添加自定义处理逻辑,并且不同 IOC 容器间的 BeanPostProcessor 不会相互干预。
也可以配置多个BeanPostProcessor实例,通过设置order属性来控制BeanPostProcessor实例的执行顺序。

1)创建 bean

public class Dog implements InitializingBean {public void initMethod() {System.out.println("initMethod ...");}@PostConstructpublic void postConstruct() {System.out.println("@PostConstruct ...");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean ...");}
}

2)创建配置类

@Configuration
public class Config {@Bean(initMethod = "initMethod")public Dog dog() {return new Dog();}
}

3)创建两个后置处理器

@Component
public class InstantiationTracingBeanPostProcessor1 implements BeanPostProcessor, Ordered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Dog) {System.out.println("【第一个后置处理器】拦截到Bean的初始化之前:" + bean);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Dog) {System.out.println("【第一个后置处理器】拦截到Bean的初始化之后:" + bean);}return bean;}@Overridepublic int getOrder() {return 1;}
}
@Component
public class InstantiationTracingBeanPostProcessor2 implements BeanPostProcessor, Ordered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Dog) {System.out.println("【第二个后置处理器】拦截到Bean的初始化之前:" + bean);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Dog) {System.out.println("【第二个后置处理器】拦截到Bean的初始化之后:" + bean);}return bean;}@Overridepublic int getOrder() {return 2;}
}

4)测试执行

public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.study.spring.postprocessor");}
}

输出结果:

【第一个后置处理器】拦截到Bean的初始化之前:com.study.spring.postprocessor.Dog@7f9fcf7f
【第二个后置处理器】拦截到Bean的初始化之前:com.study.spring.postprocessor.Dog@7f9fcf7f
@PostConstruct ...
InitializingBean ...
initMethod ...
【第一个后置处理器】拦截到Bean的初始化之后:com.study.spring.postprocessor.Dog@7f9fcf7f
【第二个后置处理器】拦截到Bean的初始化之后:com.study.spring.postprocessor.Dog@7f9fcf7f

由此得出 bean 的初始化阶段的全流程:BeanPostProcessor#postProcessBeforeInitialization → @PostConstruct → InitializingBean → init-method → BeanPostProcessor#postProcessAfterInitialization

参考资料:《从 0 开始深入学习Spring小册》

相关文章:

Spring Bean 的生命周期详解

所谓万物皆对象&#xff0c;对于一个 bean 而言&#xff0c;从出生到死亡&#xff0c;他要经历哪些阶段呢&#xff1f; 生命周期 理解对象的生命周期&#xff0c;可以帮助我们更好的做一些扩展。 一个对象从被创建到被垃圾回收&#xff0c;可以大致分为这 5 个阶段&#xff1a…...

MySQL【知识改变命运】12

视图 1&#xff1a;什么是视图2&#xff1a;创建视图使用视图&#xff08;视图的好处&#xff09;2.1.隐藏敏感字段2.2.对外提供统一访问3&#xff1a;视图和真实表进⾏表连接查询 4&#xff1a;修改视图数据4.1&#xff1a;通过真实表修改数据&#xff0c;会影响视图4.2&#…...

shell编程(完整版)

目录 一、shell脚本解释器 二、shell脚本的执行 三、变量的使用 四、永久环境变量 按用户设置永久环境变量 文件路径&#xff1a; 示例步骤&#xff1a; 删除永久环境变量 五、脚本程序传递参数怎么实现 六、用编程进行数学运算 shell中利用expr进行运算 运算与变量…...

数字逻辑(一)——导论

1.导论 1.1什么是数字逻辑&#xff1f; 数字逻辑是指在数字电路设计、计算机科学领域中对于离散的二进制信号进行逻辑处理、运算、存储和传输的基本原理和方法。 1.2数字量和模拟量的区别 数字量&#xff1a;在时间上和数量上都是离散的、不连续的物理量。模拟量&#xff1…...

量化交易系统开发-实时行情自动化交易-4.4.做市策略

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来继续说说做市策略原理。 做市策…...

《线性代数的本质》

之前收藏的一门课&#xff0c;刚好期末复习&#xff0c;顺便看一看哈哈 课程链接&#xff1a;【线性代数的本质】合集-转载于3Blue1Brown官方双语】 向量究竟是什么 线性代数中最基础、最根源的组成部分就是向量&#xff0c;需要先明白什么是向量 不同专业对向量的看法 物理专…...

Gbase8s 允许内置用户创建用户以及创建只读权限用户以及利用角色管理普通用户权限

Gbase8s 允许内置用户创建用户以及创建只读权限用户以及利用角色管理普通用户权限 普通安装实例创建数据库以后,DBA权限只有gbasedbt用户。gbasdbt可以创建普通用户,并且给普通用户赋予库及权限或者表级权限。 但是gbasedbt用户口令和操作系统相关,所以想在不提供gbasedbt的…...

24/11/25 视觉笔记 深度传感器和手势识别

本章的目的是开发一个应用程序&#xff0c;使用深度传感器的输出实时检测和跟踪简单的手势。该应用程序将分析每个已捕捉的帧。并执行以下任务。 手部区域分割&#xff1a;通过分析Kinect传感器的深度图输出&#xff0c;在每一帧中提取用户的手部区域&#xff0c;这是通过阈值…...

迄今为止的排序算法总结

迄今为止的排序算法总结 7.10 迄今为止的排序算法总结复杂度和稳定性时间复杂度测试程序sortAlgorithm.hsortAlgorithm.cpptest.cpp 时间复杂度测试结果 7.10 迄今为止的排序算法总结 复杂度和稳定性 排序算法平均情况最好情况最坏情况稳定性空间复杂度选择排序O(n^2)O(n^2)O…...

HTML和CSS 表单、表格练习

HTML和CSS 表格练习 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>HTML表格练习</title>…...

H5流媒体播放器EasyPlayer.js网页直播/点播播放器如果H.265视频在播放器上播放不流畅,可以考虑的解决方案

随着流媒体技术的迅速发展&#xff0c;H5流媒体播放器已成为现代网络视频播放的重要工具。其中&#xff0c;EasyPlayer.js网页直播/点播播放器作为一款功能强大的H5播放器&#xff0c;凭借其全面的协议支持、多种解码方式以及跨平台兼容性&#xff0c;赢得了广泛的关注和应用。…...

Http 转 https 中 Nginx 的详细配置过程

摘要 本节将简要介绍从 HTTP 到 HTTPS 的配置过程&#xff0c;并完整展示 Nginx 的相关配置信息。 经过两天断断续续的调试&#xff0c;终于将 http 变成 https 了。现在说说这个安装 ssl 证书的过程。 服务器是在某云上。这个过程大致分为三个步骤&#xff1a;申请 ssl 证书、…...

【测试工具JMeter篇】JMeter性能测试入门级教程(二)出炉,测试君请各位收藏了!!!

上篇文章&#xff1a;CSDN 我们介绍了JMeter的一些原理介绍&#xff0c;以及安装配置和启动流程&#xff0c;本文我们就来讲讲JMeter如何使用。 一、JMeter目录结构组成 1. 根目录 Jmeter安装包解压后的根目录如下图&#xff1a; 1.1 backups目录&#xff1a;脚本备份目录&am…...

Otter 安装流程

优质博文&#xff1a;IT-BLOG-CN 一、背景 随着公司的发展&#xff0c;订单库的数据目前已达到千万级别&#xff0c;需要进行分表分库&#xff0c;就需要对数据进行迁移&#xff0c;我们使用了otter&#xff0c;这里简单整理下&#xff0c;otter 的安装过程&#xff0c;希望对…...

一文学会Golang里拼接字符串的6种方式(性能对比)

g o l a n g golang golang的 s t r i n g string string类型是不可修改的&#xff0c;对于拼接字符串来说&#xff0c;本质上还是创建一个新的对象将数据放进去。主要有以下几种拼接方式 拼接方式介绍 1.使用 s t r i n g string string自带的运算符 ans ans s2. 使用…...

【笔记】Linux下编译Python3.10.15为动态库同时正确处理OpenSSL3依赖

之前自己第一次编译Python后发现pip会提示无法使用SSL&#xff0c;后来了解到是自己编译时没有配置OpenSSL。这个过程有点曲折&#xff0c;里面有一个坑&#xff0c;怕忘记于是写博客记录一下。 首先是下载OpenSSL&#xff0c;Python3.10.15支持此时最新版的OpenSSL 3.4.0&…...

Go语言获取客户端真实IP

在一些需求中&#xff0c;服务器需要记录客户端的ip地址&#xff0c;要获取ip地址&#xff0c;则需要有http.Request的对象参数传入&#xff0c;以下代码直接放在util中使用。 文件名&#xff1a;ip_utils.go package utilsimport ("context""github.com/spf1…...

大模型论文速递(11.23-11.25)

BlueLM-V3B 关键词&#xff1a;动态分辨率&#xff0c;图像放大&#xff0c;适应性网格化方法 研究问题&#xff1a;如何改进现有的动态分辨率匹配方法以减少在模型训练和部署中的计算复杂度&#xff1f; 方法&#xff1a; 分析现有动态分辨率匹配算法&#xff08;如LLaVA-…...

维护在线重做日志(二)

迁移和重命名 可以使用操作系统命令重新定位重做日志&#xff0c;然后使用ALTER DATABASE语句使数据库知道它们的新名称&#xff08;位置&#xff09;。这个过程是必要的&#xff0c;例如&#xff0c;如果当前用于一些重做日志文件的磁盘将被删除&#xff0c;或者如果数据文件…...

.net core MVC入门(一)

文章目录 项目地址一、环境配置1.1 安装EF core需要包1.2 配置数据库连接二、使用EF创建表2.1 整体流程梳理2.1 建表详细流程三、添加第一个视图3.1整体流程梳理3.1 添加视图,并显示在web里四、使用EF增加Catogory数据,并且读取数据到页面4.1整体流程梳理4.2 实现五、增加Cat…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...