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

Spring框架自定义实现IOC基础功能/IDEA如何手动实现IOC功能

继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用!

7.4 自定义Spring IOC

创建新模块,结构如图![[Pasted image 20230210173222.png]]

7.4.1 定义bean相关POJO类

7.4.1.1 定义propertyValue类

/**  * @Author:Phil  * @ClassName: PropertyValue  * @Description:  * 用来封装bean标签下的property标签属性  * name属性  * ref属性  * value属性:给基本数据类型及String类型赋值  * @Date 2023/2/8 21:45  * @Version: 1.0  **/public class propertyValue {  private String name;  private String ref;  private String value;  public propertyValue() {  }  public propertyValue(String name, String ref, String value) {  this.name = name;  this.ref = ref;  this.value = value;  }  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public String getRef() {  return ref;  }  public void setRef(String ref) {  this.ref = ref;  }  public String getValue() {  return value;  }  public void setValue(String value) {  this.value = value;  }  
}

7.4.1.2 定义MultiplePropertyValue类

一个bean 标签可以有多个property子标签,故用multiplePropertyValue类来存储PropertyValue对象

public class MultiplePropertyValues implements Iterable<PropertyValue>{  
//    定义list集合对象,用来存储PropertyValue对象  private final List<PropertyValue> propertyValueList;  public MultiplePropertyValues() {  this.propertyValueList = new ArrayList<PropertyValue> ();  }  public MultiplePropertyValues(List<PropertyValue> propertyValueList) {  if(propertyValueList == null)  this.propertyValueList = new ArrayList<PropertyValue>();  else            this.propertyValueList = propertyValueList;  }  
//    获取所有propertyValue对象,以数组形式返回  public PropertyValue[] getPropertyValues(){  return propertyValueList.toArray(new PropertyValue[0]);  }  
//    根据name属性值返回对应PropertyValue对象  public PropertyValue getPropertyValues(String propertyName){  
//        遍历集合返回  for (PropertyValue propertyValue : propertyValueList) {  if(propertyValue.getName().equals(propertyName))  return propertyValue;  }  return null;  }  
//    判断集合是否为空  public boolean isEmpty(){  return propertyValueList.isEmpty();  }  
//    添加PropertyValue对象  public MultiplePropertyValues addPropertyValue(PropertyValue pv){  
//        若有则进行覆盖  for (int i = 0; i < propertyValueList.size(); i++) {  if(propertyValueList.get(i).getName().equals(pv.getName())){  propertyValueList.set(i,pv);  return this;//目的是链式编程  }  }  
//            添加新的  this.propertyValueList.add(pv);  return this;    }  
//    判断是否有指定name的PropertyValue对象  public boolean contains(String propertyName){  return getPropertyValues(propertyName) != null;  }  
//    获取迭代器对象  @Override  public Iterator<PropertyValue> iterator() {  return propertyValueList.iterator();  }  
}

7.1.4.3 BeanDefinition类

BeanDefinition类用来封装bean信息,主要包含id(bean 名称),class(bean全类名)及子标签property对象数据

public class BeanDefinition {  private String id;  private String className;  private MultiplePropertyValues multiplePropertyValues;  public BeanDefinition() {  multiplePropertyValues = new MultiplePropertyValues();  }  public String getId() {  return id;  }  public void setId(String id) {  this.id = id;  }  public String getClassName() {  return className;  }  public void setClassName(String className) {  this.className = className;  }  public MultiplePropertyValues getMultiplePropertyValues() {  return multiplePropertyValues;  }  public void setMultiplePropertyValues(MultiplePropertyValues multiplePropertyValues) {  this.multiplePropertyValues = multiplePropertyValues;  }  
}

7.4.2 定义注册表类

7.4.2.1 定义BeanDefinitionRegistry接口

BeanDefinitionRegistry接口定义了注册表相关操作,定义如下功能:

  • 注册BeanDefinition对象到注册表中
  • 根据名称从注册表中获取后去BeanDefinition对象
  • 从注册表中删除指定名称的BeanDefinition对象
  • 判断注册表中是否包含指定名称的BeanDefinition对象
  • 获取注册表中BeanDefinition对象个数
  • 获取注册表中所有的Bean
public interface BeanDefinitionRegistry {  //往注册表中注册bean  void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) ;  //从注册表删掉指定名称bean  void removeBeanDefinition(String beanName) throws Exception;  //获取指定名称bean  BeanDefinition getBeanDefinition(String beanName) throws Exception;  //判断是否包含指定名称bean  boolean containsBeanDefinition(String beanName);  //获取所有bean  String[] getBeanDefinitionNames();  int getBeanDefinitionCount();  boolean isBeanNameInUse(String var1);  
}

7.4.2.2 SimpleBeanDefinitionRegistry类

public class SimpleBeanDefinitionRegistry implements BeanDefinitionRegistry{  
//    创建容器,用于存储  Map<String,BeanDefinition> beanDefinitionMap = new HashMap<String,BeanDefinition>();  @Override  public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {  beanDefinitionMap.put(beanName,beanDefinition);  }  @Override  public void removeBeanDefinition(String beanName) throws Exception {  beanDefinitionMap.remove(beanName);  }  @Override  public BeanDefinition getBeanDefinition(String beanName) throws Exception {  return beanDefinitionMap.get(beanName);  }  @Override  public boolean containsBeanDefinition(String beanName) {  return beanDefinitionMap.containsKey(beanName);  }  @Override  public String[] getBeanDefinitionNames() {  return beanDefinitionMap.keySet().toArray(new String[0]);  }  @Override  public int getBeanDefinitionCount() {  return beanDefinitionMap.size();  }  @Override  public boolean isBeanNameInUse(String var1) {  return beanDefinitionMap.containsKey(var1);  }  
}

7.4.3 定义解析器类

7.4.3.1 BeanDefinitionReader接口

BeanDefinitionReader用来解析配置文件并在注册表中注册bean的信息,定义了两规范:

  • 获取注册表功能,让外界可通过该对象获取注册表对象
  • 加载配置文件,并注册bean数据
public interface BeanDefinitionReader{//获取注册表对象BeanDefinitionRegistry getRegistry();//加载配置文件斌在注册表中进行注册void loadBeanDefinitions(String configuration);
}

7.4.3.2 XmlBeanDefinitionReader类

XmlBeanDefinitionReader类是专门来解析xml配置文件,实现了BeanDefinitionReader接口的两个功能。

public class XmlBeanDefinitionReader implements BeanDefinitionReader {  
//    声明注册表对象  private BeanDefinitionRegistry registry;  public XmlBeanDefinitionReader() {  this.registry = new SimpleBeanDefinitionRegistry();  }  @Override  public BeanDefinitionRegistry getRegistry() {  return registry;  }  @Override  public void loadBeanDefinitions(String configuration) throws Exception{  
//        使用dom4j进行xml配置文件的解析  SAXReader saxReader = new SAXReader();  
//        后去类路径下的配置文件  InputStream resourceAsStream = XmlBeanDefinitionReader.class.getClassLoader().getResourceAsStream(configuration);  Document document = saxReader.read(resourceAsStream);  
//        根据Document对象获取根标签对象(beans)  Element rootElement = document.getRootElement();  
//       获取根标签下所有的bean标签对象  List<Element> elements = rootElement.elements("bean");  
//        遍历集合  for (Element element : elements) {  
//            获取id属性  String id = element.attributeValue("id");  
//            获取className  String className = element.attributeValue("class");  
//          将id和className封装到BeanDefinition对象中  
//          创建BeanDefinition对象  BeanDefinition beanDefinition = new BeanDefinition();  beanDefinition.setId(id);  beanDefinition.setClassName(className);  
//            创建MultiplePropertyValue对象  MultiplePropertyValues multiplePropertyValues = new MultiplePropertyValues();  
//          获取bean标签下的所有property标签对象  List<Element> propertyElements = element.elements("property");  for (Element propertyElement : propertyElements) {  String name = propertyElement.attributeValue("name");  String ref = propertyElement.attributeValue("ref");  String value = propertyElement.attributeValue("value");  PropertyValue propertyValue = new PropertyValue(name, ref, value);  multiplePropertyValues.addPropertyValue(propertyValue);  }  
//            将multiplePropertyValues封装到BeanDefinition中  beanDefinition.setMultiplePropertyValues(multiplePropertyValues);  
//            将BeanDefinition注册到注册表中  registry.registerBeanDefinition(id,beanDefinition);  }  }  
}

7.4.4 容器相关类

7.4.4.1 BeanFactory接口

该接口定义IOC容器的统一规范即获取bean对象

public interface BeanFactory{//根据bean对象的名称获取bean对象Object getBean(String name) throws Exception;//根据bean对象的名称获取bean对象,并进行类型转换<T> T getBean(String name,Class<? extends T> clazz) throws Exception;
}

7.4.4.2 ApplicationContext接口

该接口的子实现类对bean 对象的创建都是非延时的,所以该接口定义refresh方法,主要有两功能:

  • 加载配置文件
  • 根据注册表中BeanDefinition对象封装的数据进行bean对象的创建
public interface ApplicationContext extends BeanFactory{  void refresh()throws Exception;  
}

7.4.4.3 AbstractApplicationContext接口

  • 作为ApplicationContext接口的子类,故该类是非延时加载,故需要在该类中定义Map集合,作为bean对象存储容器
  • 声明BeanDefinition类型变量,用来进行xml配置文件解析,符合单一职责原则
  • BeanDefinition类型对象创建交由子类实现,子类明确创建BeanDefinitionReader
public abstract class AbstractApplicationContext implements ApplicationContext {  
//    声明解析器对象  protected BeanDefinitionReader beanDefinitionReader;  
//   存储bean容器,key存储的bean的id,value是bean对象  protected Map<String,Object> singletonObject = new HashMap<String,Object>();;  
//    存储配置文件路径  String configLocation;  public void refresh() throws Exception{  
//   加载BeanDefinition  beanDefinitionReader.loadBeanDefinitions(configLocation);  
//       初始化bean  finishBeanInitialization();  }  public void finishBeanInitialization() throws Exception{  
//       获取注册表对象  BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();  
//        获取BeanDefinition对象  String [] beanNames = registry.getBeanDefinitionNames();  
//        初始化bean  for (String beanName : beanNames) {  getBean(beanName);  }  }  
}

7.4.4.4 ClassPathXmlApplicationContext接口

该类主要是加载类路径下的配置文件,并进行bean对象的创建,主要有以下功能:

  • 在构造方法中,创建BeanDefinitionReader对象
  • 在构造方法中,调用refresh方法,用于进行配置文件加载,创建bean对象并存储到容器中
  • 重写父类中的getBean方法,并实现依赖注入
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{  public ClassPathXmlApplicationContext(String configLocation){  this.configLocation = configLocation;  
//        构建解析器对象  beanDefinitionReader = new XmlBeanDefinitionReader();  try {  this.refresh();  }catch (Exception exception){  exception.printStackTrace();  }  }  
//    根据bean对象的名称获取bean对象  @Override  public Object getBean(String name) throws Exception {  
//        判断对象容器中是否包含指定bean对象,若包含则返回,否则创建  Object object = singletonObject.get(name);  if(object != null)  return object;  
//        获取BeanDefinition对象  BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();  BeanDefinition beanDefinition = registry.getBeanDefinition(name);  
//       获取bean信息中的className  String className = beanDefinition.getClassName();  
//        通过反射获取对象  Class<?> clazz = Class.forName(className);  Object instance = clazz.newInstance();  
//        进行依赖注入操作  MultiplePropertyValues multiplePropertyValues = beanDefinition.getMultiplePropertyValues();  for (PropertyValue propertyValue : multiplePropertyValues) {  
//            获取name属性值  String propertyValueName = propertyValue.getName();  
//            获取value值  String value = propertyValue.getValue();  
//            获取ref值  String ref = propertyValue.getRef();  if(ref != null && !"".equals(ref)){  
//                获取依赖的对象  Object bean = getBean(ref);  
//                拼接方法名  String setterMethodByField = StringUtils.getSetterMethodByField(propertyValueName);  
//                获取所有方法  Method[] methods = clazz.getMethods();  for (Method method : methods) {  if(method.getName().equals(setterMethodByField))  
//                        执行setter方法  method.invoke(instance,bean);  }  }  if(value != null && !"".equals(value)){  
//                拼接方法名  String methodName = StringUtils.getSetterMethodByField(propertyValueName);  
//                获取method对象  Method method = clazz.getMethod(methodName, String.class);  method.invoke(instance, value);  }  }  
//        在返回instance对象之前,将该对象存储到map容器中  singletonObject.put(name,instance);  return instance;  }  @Override  public <T> T getBean(String name, Class<? extends T> clazz) throws Exception {  Object bean = getBean(name);  if(bean == null)  return null;  return clazz.cast(bean);  }  
}

7.4.4.5 测试

将前文回顾Spring框架项目中的pom文件的spring-context依赖换为上述新建项目依赖,如图
![[Pasted image 20230210173346.png]]
运行后如图
![[Pasted image 20230210173447.png]]

7.4.5 总结

7.4.5.1 使用到的设计模式

  • 工厂模式:工厂模式+ 配置文件
  • 单例模式。Spring IOC管理的bean都是单例的,此处单例不是通过构造器进行单例构建,且框架对每个bean只创建一个对象。
  • 模板方法模式。AbstractApplicationContext类中的finishInitialization方法调用getBean方法,因为getBean实现和环境有关。
  • 迭代器模式。其中MultiplePropertyValyes类使用了迭代器模式,因为此类存储并管理PropertyValue对象,也属于一个容器。
  • 还使用了很多设计模式,如AOP使用到了代理模式,选择JDK代理或CGLIB代理使用了策略模式,还有适配器模式,装饰者模式,观察者模式等。

7.4.5.2 符合大部分设计原则

7.4.5.3 整个设计和Spring设计还有一定出入

Spring框架底层是很复杂的,进行了很深入的封装,并对外提供了很好的扩展性,自定义Spring IOC容器有两目的:

  • 了解Spring底层对对象的大体管理机制
  • 了解设计模式在具体开发中的使用
  • 以后学习Spring源码,通过该案例实现,可以降低Spring学习入门成本

相关文章:

Spring框架自定义实现IOC基础功能/IDEA如何手动实现IOC功能

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用&#xff01; 7.4 自定义Spring IOC 创建新模块&#xff0c;结构如图![[Pasted image 20230210173222.png]] 7.4.1 定义bean相关POJO类 7.4.1.1 定义propertyValue类 /** …...

pip离线安装windows版torch

文章目录前言conda创建虚拟环境安装torchtorch官网在线安装离线手动安装测试是否安装成功后记前言 学习的时候遇到几个机器学习相关的项目&#xff0c;由于不同的项目之间用到的依赖库不太一样&#xff0c;于是想利用conda为不同的项目创建不同的环境方便管理和运行&#xff0…...

Redis核心知识点

Redis核心知识点Redis核心知识点大全五种数据类型redis整合SpringBoot序列化问题渐进式扫描慢查询缓存相关问题数据库和缓存谁先更新缓存穿透缓存雪崩缓存击穿实际应用超卖问题分布式锁全局唯一ID充当消息队列Feed流附近商户签到HyperLogLog实现UV统计持久化RDBAOF持久化小结事…...

14. 最长公共前缀

14. 最长公共前缀 一、题目描述&#xff1a; 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 “”。 示例 1&#xff1a; 输入&#xff1a;strs [“flower”,“flow”,“flight”] 输出&#xff1a;“fl” 示例 2&#xff1a; …...

SignalR注册成Windows后台服务,并实现web前端断线重连

注意下文里面的 SignalR 不是 Core 版本&#xff0c;而是 Framework 下的 本文使用的方式是把 SignalR 写在控制台项目里&#xff0c;再用 Topshelf 注册成 Windows 服务 这样做有两点好处 传统 Window 服务项目调试时需要“附加到进程”&#xff0c;开发体验比较差&#xf…...

【前端笔试题二】从一个指定数组中,每次随机取一个数,且不能与上次取数相同,即避免相邻取数重复

前言 本篇文章记录下我在笔试过程中遇到的真实题目&#xff0c;供大家参考。 1、题目 系统给定一个数组&#xff0c;需要我们编写一个函数&#xff0c;该函数每次调用&#xff0c;随机从该数组中获取一个数&#xff0c;且不能与上一次的取数相同。 2、思路解析 数组已经有了…...

专栏关注学习

Node学习专栏&#xff08;全网最细的教程&#xff09; 【spring系列】 SpringCloud 前端框架Vue java学习过程 RocketMQ Spring Tomcat websocket 从头开始学Redisson 从头开始学Oracle 跟着大宇学Shiro 吃透Shiro源代码 Git基础与进阶 Java并发编程 Spring系列 手写…...

【手写 Vuex 源码】第八篇 - Vuex 的 State 状态安装

一&#xff0c;前言 上一篇&#xff0c;主要介绍了 Vuex 模块安装的实现&#xff0c;针对 action、mutation、getter 的收集与处理&#xff0c;主要涉及以下几个点&#xff1a; Vuex 模块安装的逻辑&#xff1b;Vuex 代码优化&#xff1b;Vuex 模块安装的实现&#xff1b;Vue…...

Mac下拉式终端的安装与配置 (iTerm2)

Mac下拉式终端的安装与配置 使用效果如图所示 安装前置软件 iTerm2 很可惜&#xff0c;如此炫酷的功能在原终端中并不能实现&#xff0c;我们需要借助iTerm2这个软件来实现。 官网链接&#xff1a;iTerm2 - macOS Terminal Replacement 我们点击download下载即可 配置 当我…...

使用 Spring 框架结合阿里云 OSS 实现文件上传的代码示例

使用 Spring 框架结合阿里云 OSS 实现文件上传的代码示例POM文件配置文件上传工具类控制层使用yaml配置文件&#xff08;第二种用法&#xff0c;看公司要求&#xff09;注入 OSSClient 对象及工具类&#xff08;第二种用法&#xff0c;看公司要求&#xff09;使用 Vue 前端代码…...

神经网络基础知识

神经网络基础知识 文章目录神经网络基础知识一、人工神经网络1.激活函数sigmod函数Tanh函数Leaky Relu函数分析2.过拟合和欠拟合二、学习与感知机1.损失函数与代价函数2. 线性回归和逻辑回归3. 监督学习与无监督学习三、优化1.梯度下降法2.随机梯度下降法(SGD)3. 批量梯度下降法…...

SpringBoot开发规范部分通用模板+idea配置【项目通用-1】

SpringBoot开发规范通用模板 1 分页插件使用 通过MybatisPlus配置分页插件拦截器 Configuration MapperScan("com.xuecheng.content.mapper") //拦截的mapper层 public class MybatisPlusConfig {//定义分页的拦截器Beanpublic MybatisPlusInterceptor getMybatisPl…...

程序的机器级表示part3——算术和逻辑操作

目录 1.加载有效地址 2. 整数运算指令 2.1 INC 和 DEC 2.2 NEG 2.3 ADD、SUB 和 IMUL 3. 布尔指令 3.1 AND 3.2 OR 3.3 XOR 3.4 NOT 4. 移位操作 4.1 算术左移和逻辑左移 4.2 算术右移和逻辑右移 5. 特殊的算术操作 1.加载有效地址 指令效果描述leaq S, DD…...

基于YOLOV5的钢材缺陷检测

数据和源码见文末 1.任务概述 数据集使用的是东北大学收集的一个钢材缺陷检测数据集,需要检测出钢材表面的6种划痕。同时,数据集格式是VOC格式,需要进行转化,上传的源码中的数据集是经过转换格式的版本。 2.数据与标签配置方法 在数据集目录下,train文件夹下有训练集数据…...

Session与Cookie的区别(三)

中场休息 让我们先从比喻回到网络世界里&#xff0c;HTTP 是无状态的&#xff0c;所以每一个 Request 都是不相关的&#xff0c;就像是对小明来说每一位客人都是新的客人一样&#xff0c;他根本不知道谁是谁。 既然你没办法把他们关联&#xff0c;就代表状态这件事情也不存在。…...

七大设计原则之接口隔离原则应用

目录1 接口隔离原则介绍2 接口隔离原则应用1 接口隔离原则介绍 接口隔离原则&#xff08;Interface Segregation Principle, ISP&#xff09;是指用多个专门的接口&#xff0c;而不使用单一的总接口&#xff0c;客户端不应该依赖它不需要的接口。这个原则指导我们在设计接口时…...

【Shell1】shell语法,ssh/build/scp/upgrade,环境变量,自动升级bmc

文章目录1.shell语法&#xff1a;shell是用C语言编写的程序&#xff0c;是用户使用Linux的桥梁&#xff0c;硬件>内核(os)>shell>文件系统1.1 变量&#xff1a;readonly定义只读变量&#xff0c;unset删除变量1.2 函数&#xff1a;shell脚本传递的参数中包含空格&…...

JavaScript HTML DOM - 改变CSS

JavaScript 是一种动态语言&#xff0c;它可以动态地修改网页的外观&#xff0c;并且使用HTML DOM&#xff08;文档对象模型&#xff09;可以更方便地控制HTML元素的样式。 JavaScript 通过在HTML DOM中更改CSS属性来更改样式&#xff0c;这些CSS属性包括颜色、位置、字体大小…...

mycat连接mysql 简单配置

mycat三个配置文件位于conf下 可通过Notepad操作 首先配置service.xml中的user标签&#xff0c;设置用户名&#xff0c;密码&#xff0c;查询权限&#xff0c;是否只读等 只是设置了root用户&#xff0c;有所有权限 配置schema.xml <?xml version"1.0"?&g…...

Spring常用注解

文章目录一、Bean交给Spring管理1、Component2、Bean3、Controller4、Service5、Repository6、Configuration7、ComponentScan二、作用域1、Lazy(false)Scope三、依赖注入1、Autowired2、Resource3、Qualifier四、读取配置文件值1、Value一、Bean交给Spring管理 1、Component …...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#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…...