【学习笔记】手写一个简单的 Spring IOC

目录

一、什么是 Spring IOC?

二、IOC 的作用

1. IOC 怎么知道要创建哪些对象呢?

2. 创建出来的对象放在哪儿?

3. 创建出来的对象如果有属性,如何给属性赋值?

三、实现步骤

1. 创建自定义注解

2. 创建 IOC 容器

1. 创建 Bean 定义类

2. 创建 IOC 容器

3. 扫描包

4. 使用自定义注解

5. 在 Servlet 中初始化 IOC 对象

6. 测试

3. 实例化 Bean 

测试

4. 设置属性

1. 创建一个Controller

2. 属性赋值

3. 测试

四、使用 Bean

1. 创建获取 Bean 的方法

2. 使用 Bean 

3. 测试

五、优化 IOC 容器


一、什么是 Spring IOC?

Spring 的核心之一是 IOC,全称 Inversion Of Control ,控制反转,用来统一管理 Bean

二、IOC 的作用

IOC 的作用就是帮程序员创建 Bean 对象

1. IOC 怎么知道要创建哪些对象呢?

xml 配置文件中指定要创建哪些对象,或者使用注解的方式

如果使用注解的方式,需要自定义注解,自定义注解说白了就是告诉 JVM 这个 Bean 不同于其他普通的 Bean ,它有其他的用途,标记一下。

@Component、@Controller、@Service 可以用于创建 Bean 的注解

2. 创建出来的对象放在哪儿?

先记录需要被创建的 Bean 对象的信息,存到 HashMap 中,然后根据 HashMap 中存储的Bean 的信息创建对象,存到IOC容器中

3. 创建出来的对象如果有属性,如何给属性赋值?

使用注解 @Autowired

三、实现步骤

1. 创建自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {String value() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {String value() default "";
}

2. 创建 IOC 容器

扫描包,判断类上是否有注解,如果有,存储需要被创建的对象的id,也就是全类名。

定义一个类用于存储这些信息,这个类就是 BeanDefinition  叫做 Bean 定义类,Bean 定义类创建对象后称为 Bean 定义对象,这个对象存储了 Bean 的信息

然后把 Bean 定义对象存放到 HashMap 中,这个 Map 叫做 Bean 定义Map

1. 创建 Bean 定义类

package com.shao.IOC;public class BeanDefinition {private String id;private String className;public BeanDefinition() {}public BeanDefinition(String id, String className) {this.id = id;this.className = className;}/*** 获取** @return id*/public String getId() {return id;}/*** 设置** @param id*/public void setId(String id) {this.id = id;}/*** 获取** @return className*/public String getClassName() {return className;}/*** 设置** @param className*/public void setClassName(String className) {this.className = className;}public String toString() {return "BeanDefinition{id = " + id + ", className = " + className + "}";}
}

2. 创建 IOC 容器

3. 扫描包

扫描包需要先知道路径是什么,从哪开始

这里扫描的是编译后的 class 文件,并不是类文件,因为程序运行后使用的是编译后的文件

那如何从这里开始呢?

使用类加载器获取路径

package com.shao.IOC;import com.shao.Annotation.Controller;
import com.shao.Annotation.Service;import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;/*** ApplicationContext 类. 当作 IOC 容器** @author shao.*/
public class ApplicationContext {/*** Bean 定义Map   存储Bean 定义对象*/private HashMap<String, BeanDefinition> beanDefinitionMap = new HashMap<>();/*** Bean 实例Map 存储Bean 实例对象*/private HashMap<String, Object> BeanMap = new HashMap<>();public ApplicationContext(String basePackage) throws UnsupportedEncodingException {scanPackage(basePackage);}/*** 1. 扫描包,扫描需要被创建的类,创建 Bean 定义对象,并放入 Bean 定义Map中*/public void scanPackage(String basePackage) throws UnsupportedEncodingException {
//        String basePackage = "com.shao";// 获取类加载器ClassLoader classLoader = this.getClass().getClassLoader();// 获取包路径String path = classLoader.getResource(basePackage.replace(".", "/")).getPath();// 路径解码,如果路径有空格或者中文,会出现 16 进制的字符String packagePath = URLDecoder.decode(path, "UTF-8");// 创建文件对象File fileDir = new File(packagePath);// 获取包下的文件列表File[] files = fileDir.listFiles();for (File file : files) {if (file.isFile()) {// 判断是否是class文件if (file.getName().endsWith(".class")) {// 包路径 + 文件名 构成全类名String className = basePackage + "." + file.getName().replace(".class", "");try {// 动态加载了名为 className 的类,获取该类的 Class 对象Class<?> aClass = Class.forName(className);// 判断该类是否有 @Service 或 @Controller 注解if (aClass.isAnnotationPresent(Service.class) ||aClass.isAnnotationPresent(Controller.class)) {System.out.println("需要创建:" + className);// 将该类的类名首字母小写作为 idString id = aClass.getSimpleName().substring(0, 1).toLowerCase() + aClass.getSimpleName().substring(1);System.out.println("id:" + id);// 创建 Bean 定义对象,并放入 Bean 定义Map中beanDefinitionMap.put(id, new BeanDefinition(id, className));}} catch (ClassNotFoundException e) {e.printStackTrace();}}} else if (file.isDirectory()) {// 递归扫描子文件夹String subPackagePath = basePackage + "." + file.getName();scanPackage(subPackagePath);}}}
}

4. 使用自定义注解

5. 在 Servlet 中初始化 IOC 对象

这里为了方便测试,所以先在 Servlet 中初始化 IOC 

6. 测试

3. 实例化 Bean 

遍历 Bean 定义Map ,取出 Bean 定义对象,根据对象的信息使用反射技术创建 Bean 对象,这个时候这个 Bean 也叫裸Bean,然后存入 Bean Map 中。这一步在 Bean 的生命周期中属于 Bean 的实例化

package com.shao.IOC;import com.shao.Annotation.Controller;
import com.shao.Annotation.Service;import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;/*** ApplicationContext 类. 当作 IOC 容器** @author shao.*/
public class ApplicationContext {/*** Bean 定义Map   存储Bean 定义对象*/private HashMap<String, BeanDefinition> beanDefinitionMap = new HashMap<>();/*** Bean 实例Map 存储Bean 实例对象*/private HashMap<String, Object> BeanMap = new HashMap<>();public ApplicationContext(String basePackage) throws UnsupportedEncodingException {scanPackage(basePackage);createBean();}/*** 1. 扫描包,扫描需要被创建的类,创建 Bean 定义对象,并放入 Bean 定义Map中*/public void scanPackage(String basePackage) throws UnsupportedEncodingException {// 获取类加载器ClassLoader classLoader = this.getClass().getClassLoader();// 获取包路径String path = classLoader.getResource(basePackage.replace(".", "/")).getPath();// 路径解码,如果路径有空格或者中文,会出现 16 进制的字符String packagePath = URLDecoder.decode(path, "UTF-8");// 创建文件对象File fileDir = new File(packagePath);// 获取包下的文件列表File[] files = fileDir.listFiles();for (File file : files) {if (file.isFile()) {// 判断是否是class文件if (file.getName().endsWith(".class")) {// 包路径 + 文件名 构成全类名String className = basePackage + "." + file.getName().replace(".class", "");try {// 动态加载了名为 className 的类,获取该类的 Class 对象Class<?> aClass = Class.forName(className);// 判断该类是否有 @Service 或 @Controller 注解if (aClass.isAnnotationPresent(Service.class) ||aClass.isAnnotationPresent(Controller.class)) {System.out.println("需要创建:" + className);// 将该类的类名首字母小写作为 idString id = aClass.getSimpleName().substring(0, 1).toLowerCase() + aClass.getSimpleName().substring(1);System.out.println("id:" + id);// 创建 Bean 定义对象,并放入 Bean 定义Map中beanDefinitionMap.put(id, new BeanDefinition(id, className));}} catch (ClassNotFoundException e) {e.printStackTrace();}}} else if (file.isDirectory()) {// 递归扫描子文件夹String subPackagePath = basePackage + "." + file.getName();scanPackage(subPackagePath);}}}/*** 2. 创建 Bean 实例,并放入 Bean Map 中*/public void createBean() {// 获取 Bean 定义 Map 的 所有 idSet<String> ids = beanDefinitionMap.keySet();Iterator<String> it = ids.iterator();while (it.hasNext()) {String id = it.next();// 获取 Bean 定义对象BeanDefinition beanDefinition = beanDefinitionMap.get(id);// 获取 Bean 定义对象中的 Bean 的全类名String className = beanDefinition.getClassName();try {// 动态加载类,并创建 Bean 实例,这时候的 Bean 是裸BeanObject bean = Class.forName(className).newInstance();// 将 Bean 实例放到 Bean Map 中BeanMap.put(id, bean);} catch (Exception e) {e.printStackTrace();}}System.out.println("实例化 Bean 完成");System.out.println(BeanMap);}
}

测试

4. 设置属性

给Bean 对象做初始化,也就是依赖注入。Bean 的生命周期中属于 Bean 的初始化

这里是使用类作为属性进行依赖注入,不是接口,后续需要优化

1. 创建一个Controller

使用 @Autowired 注解,这里为了方便测试,重写一下 toString 方法

2. 属性赋值
package com.shao.IOC;import com.shao.Annotation.Autowired;
import com.shao.Annotation.Controller;
import com.shao.Annotation.Service;import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;/*** ApplicationContext 类. 当作 IOC 容器** @author shao.*/
public class ApplicationContext {/*** Bean 定义Map   存储Bean 定义对象*/private HashMap<String, BeanDefinition> beanDefinitionMap = new HashMap<>();/*** Bean 实例Map 存储Bean 实例对象*/private HashMap<String, Object> BeanMap = new HashMap<>();public ApplicationContext(String basePackage) throws UnsupportedEncodingException {scanPackage(basePackage);createBean();injectBean();}/*** 1. 扫描包,扫描需要被创建的类,创建 Bean 定义对象,并放入 Bean 定义Map中*/public void scanPackage(String basePackage) throws UnsupportedEncodingException {// 获取类加载器ClassLoader classLoader = this.getClass().getClassLoader();// 获取包路径String path = classLoader.getResource(basePackage.replace(".", "/")).getPath();// 路径解码,如果路径有空格或者中文,会出现 16 进制的字符String packagePath = URLDecoder.decode(path, "UTF-8");// 创建文件对象File fileDir = new File(packagePath);// 获取包下的文件列表File[] files = fileDir.listFiles();for (File file : files) {if (file.isFile()) {// 判断是否是class文件if (file.getName().endsWith(".class")) {// 包路径 + 文件名 构成全类名String className = basePackage + "." + file.getName().replace(".class", "");try {// 动态加载了名为 className 的类,获取该类的 Class 对象Class<?> aClass = Class.forName(className);// 判断该类是否有 @Service 或 @Controller 注解if (aClass.isAnnotationPresent(Service.class) ||aClass.isAnnotationPresent(Controller.class)) {System.out.println("需要创建:" + className);// 将该类的类名首字母小写作为 idString id = aClass.getSimpleName().substring(0, 1).toLowerCase() + aClass.getSimpleName().substring(1);System.out.println("id:" + id);// 创建 Bean 定义对象,并放入 Bean 定义Map中beanDefinitionMap.put(id, new BeanDefinition(id, className));}} catch (ClassNotFoundException e) {e.printStackTrace();}}} else if (file.isDirectory()) {// 递归扫描子文件夹String subPackagePath = basePackage + "." + file.getName();scanPackage(subPackagePath);}}}/*** 2. 创建 Bean 实例,并放入 Bean Map 中*/public void createBean() {// 获取 Bean 定义 Map 的 所有 idSet<String> ids = beanDefinitionMap.keySet();Iterator<String> it = ids.iterator();while (it.hasNext()) {String id = it.next();// 获取 Bean 定义对象BeanDefinition beanDefinition = beanDefinitionMap.get(id);// 获取 Bean 定义对象中的 Bean 的全类名String className = beanDefinition.getClassName();try {// 动态加载类,并创建 Bean 实例,这时候的 Bean 是裸BeanObject bean = Class.forName(className).newInstance();// 将 Bean 实例放到 Bean Map 中BeanMap.put(id, bean);} catch (Exception e) {e.printStackTrace();}}System.out.println("实例化 Bean 完成");System.out.println(BeanMap);}/*** 3. 给 Bean 设置属性,Autowired 赋值*/public void injectBean() {// 获取 Bean Map 的 所有 idIterator<String> it = BeanMap.keySet().iterator();while (it.hasNext()) {String id = it.next();// 获取 Bean 实例Object bean = BeanMap.get(id);// 获取 Bean 的 Class 对象Class<?> aClass = bean.getClass();// 获取这个类的所有属性,不包括父类的属性Field[] declaredFields = aClass.getDeclaredFields();for (Field field : declaredFields) {// 判断该属性是否有 @Autowired 注解if (field.isAnnotationPresent(Autowired.class)) {// 设置属性可访问field.setAccessible(true);try {// 给属性赋值field.set(bean, BeanMap.get(field.getName()));} catch (IllegalAccessException e) {e.printStackTrace();}}}}System.out.println("属性赋值完成");System.out.println(BeanMap);}
}

3. 测试

四、使用 Bean

1. 创建获取 Bean 的方法

要使用 Bean ,需要从IOC 容器中获取 Bean,所以还需要在 IOC 容器中提供获取 Bean 的接口

package com.shao.IOC;import com.shao.Annotation.Autowired;
import com.shao.Annotation.Controller;
import com.shao.Annotation.Service;import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;/*** ApplicationContext 类. 当作 IOC 容器** @author shao.*/
public class ApplicationContext {/*** Bean 定义Map   存储Bean 定义对象*/private HashMap<String, BeanDefinition> beanDefinitionMap = new HashMap<>();/*** Bean 实例Map 存储Bean 实例对象*/private HashMap<String, Object> BeanMap = new HashMap<>();public ApplicationContext(String basePackage) throws UnsupportedEncodingException {scanPackage(basePackage);createBean();injectBean();}/*** 1. 扫描包,扫描需要被创建的类,创建 Bean 定义对象,并放入 Bean 定义Map中*/public void scanPackage(String basePackage) throws UnsupportedEncodingException {// 获取类加载器ClassLoader classLoader = this.getClass().getClassLoader();// 获取包路径String path = classLoader.getResource(basePackage.replace(".", "/")).getPath();// 路径解码,如果路径有空格或者中文,会出现 16 进制的字符String packagePath = URLDecoder.decode(path, "UTF-8");// 创建文件对象File fileDir = new File(packagePath);// 获取包下的文件列表File[] files = fileDir.listFiles();for (File file : files) {if (file.isFile()) {// 判断是否是class文件if (file.getName().endsWith(".class")) {// 包路径 + 文件名 构成全类名String className = basePackage + "." + file.getName().replace(".class", "");try {// 动态加载了名为 className 的类,获取该类的 Class 对象Class<?> aClass = Class.forName(className);// 判断该类是否有 @Service 或 @Controller 注解if (aClass.isAnnotationPresent(Service.class) ||aClass.isAnnotationPresent(Controller.class)) {System.out.println("需要创建:" + className);// 将该类的类名首字母小写作为 idString id = aClass.getSimpleName().substring(0, 1).toLowerCase() + aClass.getSimpleName().substring(1);System.out.println("id:" + id);// 创建 Bean 定义对象,并放入 Bean 定义Map中beanDefinitionMap.put(id, new BeanDefinition(id, className));}} catch (ClassNotFoundException e) {e.printStackTrace();}}} else if (file.isDirectory()) {// 递归扫描子文件夹String subPackagePath = basePackage + "." + file.getName();scanPackage(subPackagePath);}}}/*** 2. 创建 Bean 实例,并放入 Bean Map 中*/public void createBean() {// 获取 Bean 定义 Map 的 所有 idSet<String> ids = beanDefinitionMap.keySet();Iterator<String> it = ids.iterator();while (it.hasNext()) {String id = it.next();// 获取 Bean 定义对象BeanDefinition beanDefinition = beanDefinitionMap.get(id);// 获取 Bean 定义对象中的 Bean 的全类名String className = beanDefinition.getClassName();try {// 动态加载类,并创建 Bean 实例,这时候的 Bean 是裸BeanObject bean = Class.forName(className).newInstance();// 将 Bean 实例放到 Bean Map 中BeanMap.put(id, bean);} catch (Exception e) {e.printStackTrace();}}System.out.println("实例化 Bean 完成");System.out.println(BeanMap);}/*** 3. 给 Bean 设置属性,Autowired 赋值*/public void injectBean() {// 获取 Bean Map 的 所有 idIterator<String> it = BeanMap.keySet().iterator();while (it.hasNext()) {String id = it.next();// 获取 Bean 实例Object bean = BeanMap.get(id);// 获取 Bean 的 Class 对象Class<?> aClass = bean.getClass();// 获取这个类的所有属性,不包括父类的属性Field[] declaredFields = aClass.getDeclaredFields();for (Field field : declaredFields) {// 判断该属性是否有 @Autowired 注解if (field.isAnnotationPresent(Autowired.class)) {// 设置属性可访问field.setAccessible(true);try {// 给属性赋值field.set(bean, BeanMap.get(field.getName()));} catch (IllegalAccessException e) {e.printStackTrace();}}}}System.out.println("属性赋值完成");System.out.println(BeanMap);}/*** 对外提供获取 Bean 的接口*/public Object GetBean(String id) {return BeanMap.get(id);}public <T> T GetBean(Class<T> clazz) {// 获取类名,首字母小写String id = clazz.getSimpleName().substring(0, 1).toLowerCase() + clazz.getSimpleName().substring(1);// 获取 Bean 实例Object value = BeanMap.get(id);// 判断 value 是否为 clazz 类型if (clazz.isInstance(value)) {// 安全的转换类型return clazz.cast(value);} else {return null;}}
}

2. 使用 Bean 

这里为了方便测试,在Servlet 中获取 Bean,然后调用 Bean 实例的方法

3. 测试

五、优化 IOC 容器

现在需要注入依赖的属性是类,不是接口,需要改成给接口赋值其 实现类的对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/438565.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件设计师——计算机网络

&#x1f4d4;个人主页&#x1f4da;&#xff1a;秋邱-CSDN博客☀️专属专栏✨&#xff1a;软考——软件设计师&#x1f3c5;往期回顾&#x1f3c6;&#xff1a;软件设计师——操作系统&#x1f31f;其他专栏&#x1f31f;&#xff1a;C语言_秋邱 一、OSI/ RM七层模型(⭐⭐⭐)…

Windows安装Vim,并在PowerShell中直接使用vim

大家好啊&#xff0c;我是豆小匠。 这期介绍下怎么在windows的PowerShell上使用vim&#xff0c;方便在命令行里修改配置文件等。 先上效果图&#xff1a; 1、下载Vim GitHub传送门&#xff1a;https://github.com/vim/vim-win32-installer/releases 选择win-64的版本下载即可&…

HIKVISION 海康威视对讲服务配置平台弱口令

漏洞描述 杭州海康威视系统技术有限公司对讲服务配置平台存在弱口令 漏洞复现 FOFA "document.write(TITLE_SYSTEM);" POC admin #账号 12345 #密码 登录成功

.net Framework 4.6 WebAPI 使用Hangfire

C# 使用 Hangfire 第一章 .net Framework 4.6 WebAPI 使用Hangfire 文章目录 C# 使用 Hangfire前言一、hangfire是什么?二、hangfire的特点三、.net Framework 中hangfire的使用方法第一步:创建WebAPI控制器第二步:添加nuget包第三步 创建startup类新建项目startup类Startu…

算法笔记(七)——哈希表

文章目录 两数之和判定是否互为字符重排存在重复元素存在重复元素 II字母异位词分组 哈希表&#xff1a;一种存储数据的容器&#xff1b; 可以快速查找某个元素&#xff0c;时间复杂度O(1)&#xff1b; 当频繁查找某一个数时&#xff0c;我们可以使用哈希表 创建一个容器&#…

19款奔驰E300升级新款触摸屏人机交互系统

《19 款奔驰 E300 的科技焕新之旅》 在汽车科技日新月异的时代&#xff0c;19 款奔驰 E300 的车主们为了追求更卓越的驾驶体验&#xff0c;纷纷选择对爱车进行升级改装&#xff0c;其中新款触摸屏人机交互系统的改装成为了热门之选。 19 款奔驰 E300 作为一款经典车型&#x…

高炉计算笔记

一、总体概述 热风炉是一种重要的工业热能设备&#xff0c;通过燃烧燃料将水加热为蒸汽&#xff0c;用于驱动各种设备。在热风炉的运行过程中&#xff0c;烟气量是一个重要的参数&#xff0c;表示热风炉内燃料的利用率及运行效率。烟气量的计算公式如下&#xff1a; Q α Q…

iterator的使用+求数组中的第n大值+十大经典排序算法

目录 一、iterator的用法 二、求一个数组中的第n大值&#xff08;n为2或者3&#xff09; 1、求一个数组中的第二大值&#xff08;不能使用排序&#xff09; 2、求一个数组中的第三大值&#xff08;不能使用排序&#xff09; 三、冒泡排序 1、基本思想 2、代码实现 3、存…

【Unity踩坑】Unity更新Google Play结算库

一、问题描述&#xff1a; 在Google Play上提交了app bundle后&#xff0c;提示如下错误。 我使用的是Unity 2022.01.20f1&#xff0c;看来用的Play结算库版本是4.0 查了一下文档&#xff0c;Google Play结算库的维护周期是两年。现在需要更新到至少6.0。 二、更新过程 1. 下…

蓝桥等级考试C++组18级真题-2023-06-18

选择题 1 C L18(15分) 已定义double rate 3.921576&#xff1b;以下可以正确输出变量rate 的是()。 A printf("%d",rate)&#xff1b; B printf("%f",rate)&#xff1b; C printf("%ld",rate)&#xff1b; D printf("%r",rate)&#…

初识Linux · 进程替换

目录 前言&#xff1a; 1 直接看代码和现象 2 解释原理 3 将代码改成多进程版本 4 认识所有函数并使用 前言&#xff1a; 由前面的章节学习&#xff0c;我们已经了解了进程状态&#xff0c;进程终止以及进程等待&#xff0c;今天&#xff0c;我们学习进程替换。进程替换我…

(10)MATLAB莱斯(Rician)衰落信道仿真1

文章目录 前言一、莱斯分布随机变量二、仿真代码与结果1.仿真代码2.仿真结果画图 后续 前言 首先给出莱斯衰落信道模型&#xff0c;引入了莱斯因子K&#xff0c;并给出莱斯分布的概率密度函数公式。然后导出莱斯分布随机变量的仿真表示式&#xff0c;建立MATLAB仿真代码&#…

mysql安装及使用·1

mysql安装环境变量配置pycharm连接服务初步使用 1.略 2.安装mysql之后进入到bin目录下&#xff0c; 双击输入cmd进入控制台窗口&#xff0c;输入mysql -uroot -proot&#xff08;配置的账户&#xff09;进入mysql 配置系统变量 新增bin目录到path中&#xff0c;cmd测试 3.…

【python实操】python小程序之打印输入的列表内容以及列表去重的两种方法

引言 python小程序之打印输入的列表内容以及列表去重的两种方法 文章目录 引言一、打印输入的列表内容1.1 题目1.2 代码1.3 代码解释 二、列表去重2.1 题目2.2 代码2.2.1 set格式转换2.2.2 for循环添加到新列表 2.3 代码解释2.3.1 set形式2.3.2 for循环 三、思考3.1 打印输入的…

scrapy爬取汽车、车评数据【中】

这个爬虫我想分三期来写&#xff1a; ✅ 第一期写如何爬取汽车的车型信息&#xff1b; ✅ 第二期写如何爬取汽车的车评&#xff1b; ✅ 第三期写如何对车评嵌入情感分析结果&#xff0c;以及用简单的方法把数据插入mysql中&#xff1b; 技术基于scrapy框架、BERT语言模型、mysq…

24-10-2-读书笔记(二十二)-《契诃夫文集》(一)上([俄] 契诃夫 [译] 汝龙)啊!真想生活。

文章目录 《契诃夫文集》&#xff08;一&#xff09;上&#xff08;[俄] 契诃夫 [译] 汝龙 &#xff09;早期生活——塔甘罗格&#xff08;人物家庭简介&#xff09;学生时期——莫斯科&#xff08;写作与学习&#xff09;流浪时期——哈萨林&#xff08;游历与流浪&#xff09…

方法重载(Overload)

前言 在前面的学习中&#xff0c;我们学到了重写(Override),这里我们主要进行重载(Overload)的介绍&#xff0c;同时对重写和重载的区别进行分析。 1. 重载(Overload) #方法重载 在同一个类中定义多个同名但参数不同的方法。我们称方法与方法之间构成方法重载 在Java中&…

(C语言贪吃蛇)15.贪吃蛇吃食物

目录 前言 注意事项⚠️ 效果预览 实现方法 运行效果 新的问题&#x1f64b; 最终效果 总结 前言 我们上一节实现了解决了贪吃蛇不合理走位的情况&#xff0c;不理解的再回去看看(传送门&#xff1a;解决贪吃蛇不合理走位)&#xff0c;那么贪吃蛇自然是要吃食物的啊&…

【C++】多肽

目录 一 多肽定义 1. 多肽的构成条件 1 例一 2 例二 2. 虚函数 3. 虚函数重写的两个意外 1 协变 2 析构函数的重写 二 关键字override 和 final 1. final 2.override 三 三重对比 1. 练习 四 多肽的原理 1. 多肽调用和普通调用 2.虚函数表 3. 分析 4. 原理 …

【Matlab绘图】从Excel导入表格并进行三维绘图

前言 今天手头上拿到一份论文的xlsx数据&#xff0c;要求使用MATLAB绘制进行三维图标坐标绘制。那么我们来看看如何使用如下数据进行绘图。 如上数据所示&#xff0c;数据是一个30行25列的数据&#xff0c;数据的内容是论文某项模型模拟的结果&#xff0c;我们希望把横坐标x取…