0104BeanDefinition合并和BeanClass加载-Bean生命周期详解-spring
文章目录
- 1 前言
- 2 BeanDefinition合并
- 2.1 BeanDefinition合并在做什么?
- 2.2 BeanDefinition怎么合并
- 2.3 示例演示
- 3 Bean Class 加载
- 后记
1 前言
下面要介绍的阶段,都是在调用getBean()从容器中获取bean对象的过程中发生的操作,我们需要更多的去跟进源码。
在以后的讲解中,我们都采用API配置bean的方式,通过BeanDefinitionBuilder来完成bean的配置。
2 BeanDefinition合并
BeanDefinition合并核心方法
org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition()
2.1 BeanDefinition合并在做什么?
不管我们在定义bean的时候,bean有没有父子关系。容器在注册初始BeanDefinition后,后续的相关操作都是在使用合并后的RootBeanDefinition。RootBeanDefinition会放入mergedBeanDefinitions中。
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
- mergedBeanDefinitions:AbstractBeanFactory类中存放beanName-RootBeanDefinition键值对的map
定义了bean当然是为了使用,我们通过追踪下getBean()方法,看看是不是如上面我们所描述的一样是使用RootBeanDefinition而不是初始BeanDefinition。
factory.getBean()是调用AbstractBeanFactory中的方法,
@Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}
继续调用doGetBean()方法,
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {// 如果是别名,转换为最初的beanNameString beanName = transformedBeanName(name);Object beanInstance;// Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {// 我们第一次获取bean容器中不会有bean实例// 省略...}else {// 省略...StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);}// 后续使用中使用的是合并后的RootBeanDefinitionRootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 省略...
}
2.2 BeanDefinition怎么合并
我们通过源码来详细看看是如果合并的。在上面我们已经通过源码追踪到了执行合并的方法getMergedLocalBeanDefinition(),源码如下:
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {// Quick check on the concurrent map first, with minimal locking.RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);if (mbd != null && !mbd.stale) {// 第一次获取,mergedBeanDefinitions并不会有beanName对应的RootBeanDefinitionreturn mbd;}return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
- getBeanDefinition(beanName)获取初始注册的BeanDefinition
继续调用getMergedBeanDefinition()
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)throws BeanDefinitionStoreException {return getMergedBeanDefinition(beanName, bd, null);}
继续调用getMergedBeanDefinition()即合并BeanDefinition的主要方法
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)throws BeanDefinitionStoreException {synchronized (this.mergedBeanDefinitions) {RootBeanDefinition mbd = null;RootBeanDefinition previous = null;// Check with full lock now in order to enforce the same merged instance.if (containingBd == null) {mbd = this.mergedBeanDefinitions.get(beanName);}if (mbd == null || mbd.stale) {previous = mbd;if (bd.getParentName() == null) {// 父bean为空// Use copy of given root bean definition.if (bd instanceof RootBeanDefinition) {// 原始的BeanDefinition为RootBeanDefinition,直接克隆mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();}else {// 原始的BeanDefinition不是RootBeanDefinition,newmbd = new RootBeanDefinition(bd);}}else {// 父bean不为空,需要合并BeanDefinition pbd;try {String parentBeanName = transformedBeanName(bd.getParentName());if (!beanName.equals(parentBeanName)) {// 默认beanName唯一,获取map中parentBeanName对应的RootBeanDefinitionpbd = getMergedBeanDefinition(parentBeanName);}// 省略...// new,深拷贝mbd = new RootBeanDefinition(pbd);// 子bean初始BeanDefinition的相关信息覆盖掉继承自RootBeanDefinition的相同信息mbd.overrideFrom(bd);}// 省略...return mbd;}}
合并逻辑如下:
-
我们定义的bean没有父子关系时,合并bean其实就是新生成RootBeanDefinition对象,内容拷贝自初始BeanDefinition,并放入mergedBeanDefinitions集合;如果bean就是定义的RootBeanDefinition,直接拷贝。
-
我们定义bean的有父子bean关系时,此时子BeanDefinition中的信息是不完整的,比如设置属性的时候配置在父BeanDefinition中,此时子BeanDefinition中是没有这些信息的。需要将子bean的BeanDefinition和从mergedBeanDefinitions集合获取的父bean对应的RootBeanDefinition进行合并,得到最终的一个RootBeanDefinition,合并之后得到的RootBeanDefinition包含bean定义的所有信息,包含了从父bean中继继承过来的所有信息,后续bean的所有创建工作就是依靠合并之后RootBeanDefinition来进行的。
-
当定义的bean有多级父子关系,重复上述步骤;合并当前bean的初始BeanDefinition和从mergedBeanDefinitions 映射中获取父beanName对应的RootBeanDefinition。
2.3 示例演示
因为是做演示测试,没有通过factory.getBean()去debug调试,而是直接调用getMergedBeanDefinition()方法。
// User
package com.gaogzhen.myspring.bean;/*** @author: Administrator* @version: 1.0* @createTime: 2023/02/20 07:49*/
public class User {private String name;public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +'}';}
}// 测试方法public void testMergeAPI() {DefaultListableBeanFactory factory = new DefaultListableBeanFactory();BeanDefinitionBuilder builder1 = BeanDefinitionBuilder.genericBeanDefinition(User.class).addPropertyValue("name", "张三").addPropertyValue("desc", "创立张氏制药厂");factory.registerBeanDefinition("user1", builder1.getBeanDefinition());BeanDefinitionBuilder builder2 = BeanDefinitionBuilder.genericBeanDefinition().addPropertyValue("name", "张小三").addPropertyValue("desc", "接管张氏制药厂").addPropertyValue("manage", "开设分厂").setParentName("user1");factory.registerBeanDefinition("user2", builder2.getBeanDefinition());BeanDefinitionBuilder builder3 = BeanDefinitionBuilder.genericBeanDefinition().addPropertyValue("name", "张小小三").addPropertyValue("operate", "成立张氏制药集团并上市").setParentName("user2");factory.registerBeanDefinition("user3", builder3.getBeanDefinition());//遍历容器中注册的所有bean信息for (String beanName : factory.getBeanDefinitionNames()) {//通过bean名称获取原始的注册的BeanDefinition信息BeanDefinition beanDefinition = factory.getBeanDefinition(beanName);//获取合并之后的BeanDefinition信息BeanDefinition mergedBeanDefinition = factory.getMergedBeanDefinition(beanName);// 获取beanSystem.out.println(beanName);System.out.println("初始beanDefinition:" + beanDefinition);System.out.println("beanDefinition中的属性信息" + beanDefinition.getPropertyValues());System.out.println("-----------");System.out.println("合并之后mergedBeanDefinition:" + mergedBeanDefinition);System.out.println("mergedBeanDefinition中的属性信息" + mergedBeanDefinition.getPropertyValues());System.out.println("=================================");}}
打印输出:
user1
初始beanDefinition:Generic bean: class [com.gaogzhen.myspring.bean.User]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
beanDefinition中的属性信息PropertyValues: length=2; bean property 'name'; bean property 'desc'
-----------
合并之后mergedBeanDefinition:Root bean: class [com.gaogzhen.myspring.bean.User]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
mergedBeanDefinition中的属性信息PropertyValues: length=2; bean property 'name'; bean property 'desc'
=================================
user2
初始beanDefinition:Generic bean with parent 'user1': class [null]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
beanDefinition中的属性信息PropertyValues: length=3; bean property 'name'; bean property 'desc'; bean property 'manage'
-----------
合并之后mergedBeanDefinition:Root bean: class [com.gaogzhen.myspring.bean.User]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
mergedBeanDefinition中的属性信息PropertyValues: length=3; bean property 'name'; bean property 'desc'; bean property 'manage'
=================================
user3
初始beanDefinition:Generic bean with parent 'user2': class [null]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
beanDefinition中的属性信息PropertyValues: length=2; bean property 'name'; bean property 'operate'
-----------
合并之后mergedBeanDefinition:Root bean: class [com.gaogzhen.myspring.bean.User]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
mergedBeanDefinition中的属性信息PropertyValues: length=4; bean property 'name'; bean property 'desc'; bean property 'manage'; bean property 'operate'
=================================Process finished with exit code 0
- 从输出的结果中可以看到,合并之前,BeanDefinition是不完整的,比比如user2和user3中的class是null,属性信息也不完整,但是合并之后这些信息都完整了。
bean生命周期的后续阶段使用的是合并后的RootBeanDefinition。没有父bean的直接new RootBeanDefinition,属性拷贝自该bean的初始BeanDefinition;有父bean的,深拷贝父bean对应的RootBeanDefinition,然后用该bean的初始BeanDefinition覆盖相同属性。
3 Bean Class 加载
这个阶段就是将bean的class名称转换为Class类型的对象。
BeanDefinition中有个Object类型的字段:beanClass
private volatile Object beanClass;
用来表示bean的class对象,通常这个字段的值有2种类型,一种是bean对应的Class类型的对象,另一种是bean对应的Class的类名(或者类路径),第一种情况不需要解析,第二种情况:即这个字段是bean的类名的时候,就需要通过类加载器将其转换为一个Class对象。
此时会对阶段4中合并产生的RootBeanDefinition中的beanClass进行解析,将bean的类名转换为Class对象,然后赋值给beanClass字段。
源码位置:
org.springframework.beans.factory.support.AbstractBeanFactory#resolveBeanClass()
在BeanDefinition合并阶段,我们追踪到了AbstracBeanFactory的doGetbean方法,完成BeanDefinition合并,我们继续追踪,看下在哪里完成beanClass的加载?具体加载怎么做的?
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {// 省略RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// 省略// Create bean instance.if (mbd.isSingleton()) {// 我们通常bean scope都是单例的sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});
// 省略...
}
getSingleton()方法获取bean的单例实例
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "Bean name must not be null");synchronized (this.singletonObjects) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {if (this.singletonsCurrentlyInDestruction) {// 省略...try {singletonObject = singletonFactory.getObject();// 省略
}
singletonObject初始为空,通过上一步传递的singletonFactory获取实例,即箭头函数里面return createBean(beanName, mbd, args),继续看下createBean()方法,继续调用AbstractAutowireCapableBeanFactory中的createBean()方法:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {RootBeanDefinition mbdToUse = mbd;// 这里解析beanClassClass<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 省略..
}
继续调用AbstractBeanFactory中的resolveBeanClass()方法
@Nullable
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)throws CannotLoadBeanClassException {try {if (mbd.hasBeanClass()) {return mbd.getBeanClass();}return doResolveBeanClass(mbd, typesToMatch);
// 省略异常处理
}public boolean hasBeanClass() {return (this.beanClass instanceof Class);}
- 先判断RootBeanDefinition mbd中beanClass是否是Class类型,是直接返回
- 不是说明是类路径字符串,调用doResolveBeanClass解析
查看doResolveBeanClass()方法
@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)throws ClassNotFoundException {ClassLoader beanClassLoader = getBeanClassLoader();ClassLoader dynamicLoader = beanClassLoader;boolean freshResolve = false;// 省略...String className = mbd.getBeanClassName();if (className != null) {Object evaluated = evaluateBeanDefinitionString(className, mbd);if (!className.equals(evaluated)) {// 省略...}// Resolve regularly, caching the result in the BeanDefinition...return mbd.resolveBeanClass(beanClassLoader);
}
- 如果指定了beanExpressionResolver,通过beanExpressionResolver解析,默认未指定
我们继续查找AbstracBeanDefinition 的resolveBeanClass方法
@Nullablepublic Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {String className = getBeanClassName();if (className == null) {return null;}Class<?> resolvedClass = ClassUtils.forName(className, classLoader);this.beanClass = resolvedClass;return resolvedClass;}
classUtils的forName()方法
public static Class<?> forName(String name, @Nullable ClassLoader classLoader)throws ClassNotFoundException, LinkageError {Assert.notNull(name, "Name must not be null");Class<?> clazz = resolvePrimitiveClassName(name);if (clazz == null) {clazz = commonClassCache.get(name);}if (clazz != null) {return clazz;}// 省略.. 非常规ClassLoader clToUse = classLoader;if (clToUse == null) {clToUse = getDefaultClassLoader();}try {return Class.forName(name, false, clToUse);}// 异常处理..
}
- 通常我们配置的类路径形式:包名+类名字符串,通过Class.forName(name, false, clToUse)加载。
后记
❓QQ:806797785
⭐️源代码仓库地址:https://gitee.com/gaogzhen/spring6-study
参考:
[1]Spring系列之Bean生命周期详解[CP/OL].
相关文章:
0104BeanDefinition合并和BeanClass加载-Bean生命周期详解-spring
文章目录1 前言2 BeanDefinition合并2.1 BeanDefinition合并在做什么?2.2 BeanDefinition怎么合并2.3 示例演示3 Bean Class 加载后记1 前言 下面要介绍的阶段,都是在调用getBean()从容器中获取bean对象的过程中发生的操作,我们需要更多的去…...
Java集合进阶(三)
文章目录一、Map1. 概述2. 基本功能3. 遍历4. 遍历学生对象5. 集合嵌套6. 统计字符出现次数二、Collections1. 常用方法2. 学生对象排序三、模拟斗地主一、Map 1. 概述 Interface Map<K, V>:K 是键的类型,V 是值的类型。 将键映射到值的对象&…...
【网络】什么是RPC?RPC与HTTP有什么关系?
文章目录RPC是什么RPC和HTTP的关系和区别[附]关于REST论文中提到的"HTTP不是RPC"重点参考 凤凰架构-远程过程调用 既然有HTTP为什么还要有RPC? RPC是什么 RPC(Remote Procedure Call):即远程过程调用,目的是为了让计算机能够跟调用…...
[手撕数据结构]栈的深入学习-java实现
CSDN的各位uu们你们好,今天千泽带来了栈的深入学习,我们会简单的用代码实现一下栈, 接下来让我们一起进入栈的神奇小世界吧!0.速览文章一、栈的定义1. 栈的概念2. 栈的图解二、栈的模拟实现三.栈的经典使用场景-逆波兰表达式总结一、栈的定义 1. 栈的概念 栈:一种…...
2.线性表的顺序表示
数据结构很重要! 数据结构很重要!!! 数据结构很重要!!!! 思考 1.线性表的顺序表示内容有哪些?(What) 2.为什么要学线性表的顺序表示? ? (Why)…...
eps文件删除了能恢复吗?恢复误删eps文件的三种方法
eps文件格式专为矢量图像和图形而设计。虽然没有被广泛使用,但它仍然受到各种插画家和平面设计师的钟爱。eps文件十分适合创建徽标和商标设计,主要应用见于广告牌、海报和横幅。可是在使用设备过程中,难免会遇到数据丢失问题,如果…...
【C++】运算符重载练习——Date 类
文章目录👉日期类介绍👈👉日期类实现👈📕 成员变量📕 构造函数📕 对应月份天数📕 赋值重载📕 比较运算符重载📕 计算 运算符重载👉源代码…...
Redis学习(13)之Lua脚本【环境准备】
文章目录一 Lua入门环境准备1.1 Lua简介1.2 Linux 系统安装Lua1.2.1 Lua 下载1.2.2 Lua 安装1.3 Hello World1.3.1 命令行模式1.3.2 脚本文件模式1.3.3 两种脚本运行方式1.4 Win安装Lua1.4.1 LuaForWindows的安装1.4.2 SciTE修改字体大小1.4.3 SciTE中文乱码1.4.4 SciTE快捷键工…...
关于BLE的一些知识总结
数据包长度对于BLE4.0/4.1来说,一个数据包的有效载荷最大为20字节对于BLE4.2以上,数据包的有效载荷扩大为251字节传输速率在不考虑跳频间隔的情况下,最大传输速率为:1)BLE4.0/4.1的理论吞吐率为39kb/s;2&am…...
Spring框架源码分析一
如何看源码(方法论)不要忽略源码中的注释使用翻译工具先梳理脉络,然后梳理细节即总分总,先总体过一遍,再看细节,再做一个总结大胆猜测(8分靠猜),小心验证,再调…...
CSS常用内容总结(扫盲)
文章目录前言相关概念【了解】脚本语言什么是脚本语言脚本语言有什么特点常见的脚本语言什么是动态语言,什么是静态语言动态语言和静态语言两者之间有何区别CSSCSS是什么CSS的特点一、CSS代码怎么写基本语法规则引入方式内部样式内联样式表外部样式代码风格二、CSS的…...
Java启蒙之语言基础
目录 一.Java标识符和关键字 1.1Java标识符 1.2Java关键字 二.数据类型和变量的概述和关系 2.1Java变量 2.2Java的数据类型 2.2.1数据类型的分类的概述 2.2.2数据类型的转换 3.Java运算符 总结 😽个人主页:tq02的博客_CSDN博客-领域博主 &#…...
数据库系统--T-SQL数据查询功能-多表查询(超详细/设计/实验/作业/练习)
目录课程名:数据库系统内容/作用:设计/实验/作业/练习学习:T-SQL数据查询功能-多表查询一、前言二、环境与设备三、内容四、内容练习题目:对应题目答案:五、总结课程名:数据库系统 内容/作用:设…...
Spring Boot 3.0系列【14】核心特性篇之Configuration相关注解汇总介绍
有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.3 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言@Configuration@ConfigurationProperties@EnableConfigurationProperties@ConfigurationPropertiesScan@Configuratio…...
[ubuntu][jetson]给jetson增加swap空间类似于给windows加虚拟内存
具体操作如下: #打开性能模式 sudo nvpmodel -m 0 && sudo jetson_clocks #增加swap空间,防止爆内存 swapoff -a sudo fallocate -l 15G /swapfile sudo chmod 600 /var/swapfile sudo mkswap /swapfile sudo swapon /swapfile…...
小黑子—Java从入门到入土过程:第二章
Java零基础入门2.0Java系列第二章1. 注释和关键字2. 字面量3. 变量3.1 基本用法3.2 使用方式3.3 注意事项4. 变量练习5. 计算机中的数据存储5.1 计算机的存储规则5.2 进制5.3 进制间转换二进制转十八进制转十十六进制转十十进制转其他进制6. 数据类型7. 定义变量的练习8. 标识符…...
ElasticSearch搜索详细讲解与操作
全文检索基础 全文检索流程 流程: #mermaid-svg-7Eg2qFEl06PIEAxZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-7Eg2qFEl06PIEAxZ .error-icon{fill:#552222;}#mermaid-svg-7Eg2qFEl06PIEAxZ .error…...
web实现太极八卦图、旋转动画、定位、角度、坐标、html、css、JavaScript、animation
文章目录前言1、html部分2、css部分3、JavaScript部分4、微信小程序演示前言 哈哈 1、html部分 <div class"great_ultimate_eight_diagrams_box"><div class"eight_diagrams_box"><div class"eight_diagrams"><div class&…...
【LeetCode】33. 搜索旋转排序数组、1290. 二进制链表转整数
作者:小卢 专栏:《Leetcode》 喜欢的话:世间因为少年的挺身而出,而更加瑰丽。 ——《人民日报》 目录 33. 搜索旋转排序数组 1290. 二进制链表转整数 33. 搜索旋转排序数组 33. 搜索旋转排序…...
IBM Semeru Windows 下的安装 JDK 17
要搞清楚下载那个版本,请参考文章:来聊聊 OpenJDK 和 JVM 虚拟机下载地址semeru 有认证版和非认证版,主要是因为和 OpenJ9 的关系和操作系统的关系而使用不同的许可证罢了,本质代码是一样的。在 Windows 下没有认证版,…...
Lambda表达式和steram流
目录 引言: 语法: Lambda 表达式实例: demo演示: Stream流: 引言: Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。 Lambda 允许把函数作为一个方法的参数(函…...
面试必会-MySQL篇
1. Mysql查询语句的书写顺序Select [distinct ] <字段名称>from 表1 [ <join类型> join 表2 on <join条件> ]where <where条件>group by <字段>having <having条件>order by <排序字段>limit <起始偏移量,行数>2. Mysql查询语…...
Hadoop入门常见面试题与集群时间同步操作
目录 一,常用端口号 Hadoop3.x : Hadoop2.x: 二,常用配置文件: Hadoop3.x: Hadoop2.x: 集群时间同步: 时间服务器配置(必须root用户): (1)…...
JS 数组去重的方法
// 数组去重 const arr ["1", "1", "2", "3", "5", "3", "1", "5", "4"] console.log(this.deduplicate(arr)) // [1, 2, 3, 5, 4] // 数组对象去重 const arr [ { id: 1, nam…...
PMP项目管理项目沟通管理
目录1 项目沟通管理2 规划沟通管理3 管理沟通4 监督沟通1 项目沟通管理 项目沟通管理包括通过开发工件,以及执行用于有效交换信息的各种活动,来确保项目及其相关方的信息需求得以满足的各个过程。项目沟通管理由两个部分组成:第一部分是制定…...
2.JVM常识之 运行时数据区
1.JVM核心组成 2.JVM 运行时数据区(jdk8) 程序计数器:线程私有,当前线程所执行字节码的行号指示器 jvm栈:线程私有,Java 虚拟机栈为 JVM 执行 Java 方法服务 本地方法栈:线程私有,本…...
你的游戏帐号是如何被盗的
据报道,2022上半年,中国游戏市场用户规模达到了5.54亿人,游戏市场销售收入1163.1亿元,相较去年均为同比增长的情况。如此庞大的市场规模,黑色产业链是绕不开的话题。 但相较于游戏中大家常见的玩家与玩家、玩家与官方…...
C++11异步编程
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言1、std::future和std::shared_future1.1 std:future1.2 std::shared_future2、std::async3、std::promise4、std::packaged_task前言 C11提供了异步操作相关的类…...
20230310----重返学习-DOM元素的操作-时间对象-定时器
day-024-twenty-four-20230310-DOM元素的操作-时间对象-定时器 复习 获取元素 id document.getElementById() 类名 document.getElementsByClassName() 标签名 document.getElementsByTagName() name属性 document.getElementsByName() 选择器 document.querySelector()docum…...
江苏专转本转本人后悔排行榜
江苏专转本转本人后悔排行榜 一、复习的太迟: 后悔指数:五颗星。 复习越到最后,时间一天天变少,要复习的内容还有很多,很多人都后悔没有早早开始,总想着多给我两月一定会考上的。 担心时间不够用,那就努力利…...
【算法时间复杂度】学习记录
最近开算法课,开几篇文章记录一下算法的学习过程。 关于算法的重要性 学习计算机当程序员的话,在编程过程中是绕不开算法这个大矿山的,需要我们慢慢挖掘宝藏。 算法(Algorithm)是指用来操作数据、解决程序问题的一组…...
汽车车机芯片Linux系统内核编译问题总结
谈到车机,很多人会想到华为问界上装的大屏车机,号称车机的天花板,基于鸿蒙OS的,而今天谈到的车机芯片用的是linux内核Kernel,对于它的编译,很多人一时会觉得头大,的确如果工具不是很齐全,就会遇到这样那样的问题,但是过程都会有错误提示,按照错误提示基本可以解决,而…...
Android13 音量曲线调整
Android13 音量曲线调整 Android13 上配置文件的路径: /vendor/sprd/modules/audio/engineconfigurable_apm/工程目录/system/etc/audio_engine_config/audio_policy_engine_stream_volumes.xml /vendor/sprd/modules/audio/engineconfigurable_apm/工程目录/sys…...
OpenHarmony通过MQTT连接 “改版后的华为IoT平台”
一、前言 本篇文章我们使用的是BearPi-HM_Nano开发板:小熊派的主板+E53_IA1扩展板 源码用的是D6_iot_cloud_oc,点击下载BearPi-HM_Nano全量源码 那么为什么要写这篇呢? 前段时间看到OpenHarmony群里,经常有小伙伴问接入华为IoT平台的问题,他们无法正常连接到华为IoT平台等…...
SQS (Simple Queue Service)简介
mazon Simple Queue Service (SQS)是一种完全托管的消息队列服务,可以让你分离和扩展微服务、分布式系统和无服务应用程序。 在讲解SQS之前,首先让我们了解一下什么是消息队列。 消息队列 还是举一个电商的例子,一个用户在电商网站下单后付…...
高速PCB设计指南系列(三)
第一篇 高密度(HD)电路的设计 本文介绍,许多人把芯片规模的BGA封装看作是由便携式电子产品所需的空间限制的一个可行的解决方案,它同时满足这些产品更高功能与性能的要求。为便携式产品的高密度电路设计应该为装配工艺…...
【C++】C++11——左右值|右值引用|移动语义|完美转发
文章目录一、左值与右值1.概念2.引用3.注意二、右值引用的意义1.左值引用意义2.右值引用和移动语义3.容器新增三、万能引用四、完美转发一、左值与右值 1.概念 左值是什么?右值是什么? 左值是一个表示数据的表达式(如变量名或解引用的指针&…...
[ROC-RK3399-PC Pro] 手把手教你移植主线Buildroot(基于2023.02-rc3版本)
🍇 博主主页:Systemcall小酒屋🍇 博主简介:Neutionwei,C站嵌入式领域新星创作者之一,一枚热爱开源技术、喜欢分享技术心得的极客,注重简约风格,热衷于用简单的案例讲述复杂的技术&am…...
重温线性代数
前言 对于普通的数学工作者而言,掌握矩阵、线性空间的基本性质和用法比领会抽象的概念更实用。数学专业的同学需要全面深入学习近世代数的理论和演绎法则,例如模的概念和运算。 总之,我个人认为,不论是微积分、还是线性代数&…...
2023河北沃克HEGERLS甘肃金昌重型仓储项目案例|托盘式四向穿梭车智能密集存储系统在工业行业的创新应用
项目名称:自动化仓储托盘式四向穿梭车智能密集立体库项目 项目合作客户:甘肃省金昌市某集团企业 项目施工地域:甘肃省金昌市 设计与承建单位:河北沃克金属制品有限公司(自主品牌:海格里斯HEGERLS&#x…...
软件测试的案例分析 - 闰年5
文章目的 显示不同的博客能获得多少博客质量分 (这是关于博客质量分的测试 https://www.csdn.net/qc) 这个博客得了 83 分。怎么才能得到更多分数? 正文 我们谈了不少测试的名词, 软件是人写的, 测试计划和测试用例也是人写的, 人总会犯错误。错误发生…...
Linux文件基础I/O
文件IO文件的常识基础IO为什么要学习操作系统的文件操作C语言对于函数接口的使用接口函数介绍如何理解文件文件描述符重定向更新给模拟实现的shell增加重定向功能为什么linux下一切皆文件?文件的常识 1.空文件也要在磁盘占据空间 2.文件 内容 属性 3.文件操作 对…...
HTML看这一篇就够啦,HTML基础大全,可用于快速回顾知识,面试首选
HTML 1 基础 1.1 DOCTYPE <!DOCTYPE> 文档类型声明,作用就是告诉浏览器使用哪种HTML版本来显示网页。 <!DOCTYPE html> 这句代码的意思是: 当前页面采取的是 HTML5 版本来显示网页. 注意: 声明位于文档中的最前面的位置,处于 标签之前。 …...
Altium Designer(AD)软件使用记录05-PCB叠层设计
目录Altium Designer(AD)软件使用记录05-PCB叠层设计一、正片层和负片层的介绍1、正片层(Signal)2、负片层(Plane)3、内电层的分割实现二、正片层和负片层的内缩设计1、负片设置内缩20H原则2、正片铺铜设置内缩1、设置规则2、重新铺铜三、AD的层叠设计四、叠层设计需要注意的问…...
ArcGIS动态表格批量出图
一.产品介绍:ArcGIS动态表格扩展模块Mapping and Charting Solutions,可用于插入动态表格,与数据驱动结合,出图效率无敌。注:优先选择arcgis10.2.2。 二、下载连接: https://www.xsoftnet.com/share/a001CX…...
ChatGPT真神奇,但是也真焦虑
ChatGPT火爆ChatGPT的火爆程度不用说也知道。就目前来说,已经开始冲击各行业了,比如客服、智能助手、语言学习、自然语言处理等等等。。ChatGPT冲击冲击最高的可能就是中间这个段位的了。高段位无法取代,但是低段位,通过使用ChatG…...
mos管驱动与米勒平台介绍、消除
mos驱动设计 1.选择适当的驱动芯片 为了控制MOSFET,需要使用专门的驱动芯片。选择合适的芯片需要考虑MOSFET的电压和电流需求。常见的驱动芯片包括IR2110、IR2184、MIC4424等。 2.设计电路 在驱动电路中,需要加入一些电路元件来保证MOSFET的顺畅工作…...
20230311英语学习
Philosophy of Food: Guidelines for an Authentic Approach to Eating 饮食哲学:值得思考的问题 Whats Philosophical About Food? Philosophy of food finds its basis on the idea that food is a mirror.Eating mirrors the making of a self, that is, the …...
【面试题】Nginx面试题汇总(无解答)
什么是Nginx?谈谈个人都理解,项目中是否用到,为什么要用,有什么优点?为什么要用Nginx?为什么Nginx性能这么高?Nginx怎么处理请求的?什么是正向代理和反向代理?使用“反向…...
Java面试总结(六)
进程和线程的区别 根本区别: 进程时操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。 资源开销: 每个进程都有自己独立的代码和数据空间(程序上下文),进程之间的切换开销比较大&…...