Spring - 8 ( 10000 字 Spring 入门级教程 )

news2024/11/25 14:37:09

一: MyBatis

1.1 引入 MyBatis

我们学习 MySQL 数据库时,已经学习了 JDBC 来操作数据库, 但是 JDBC 操作太复杂了.

我们先来回顾⼀下 JDBC 的操作流程:

  1. 创建数据库连接池 DataSource
  2. 通过 DataSource 获取数据库连接 Connection
  3. 编写要执行带 ? 占位符的 SQL 语句
  4. 通过 Connection 及 SQL 创建操作命令对象 Statement
  5. 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值
  6. 使用 Statement 执行 SQL 语句
  7. 查询操作:返回结果集 ResultSet,更新操作:返回更新的数量
  8. 处理结果集
  9. 释放资源

对于 JDBC 来说,整个操作非常的繁琐,我们不但要拼接每⼀个参数,而且还要按照模板代码方式,⼀步步的操作数据库,并且在每次操作完,还要手动关闭连接等,而所有的这些操作步骤都需要在每个方法中重复书写. 那有没有⼀种方法,可以更单、更方便的操作数据库呢?

这就是我们要学习 MyBatis 的真正原因,它可以帮助我们更方便、更快速的操作数据
库.

1.2 什么是 MyBatis

MyBatis 是⼀款优秀的持久层框架,⽤于简化 JDBC 的开发。

持久层:指的就是持久化操作的层, 通常指数据访问层(dao), 一般用来操作数据库.

在这里插入图片描述

二: MyBatis 入门

Mybatis操作数据库的步骤:

  1. 准备工作 (创建 springboot 工程、数据库表准备、实体类)
  2. 引入 Mybatis 的相关依赖,配置 Mybatis (数据库连接信息)
  3. 编写 SQL 语句 (注解 / XML)
  4. 测试

2.1 创建工程

  1. 创建 springboot 工程,并导入 mybatis 的起步依赖、mysql 的驱动包

在这里插入图片描述

Mybatis 是⼀个持久层框架, 具体的数据存储和数据操作还是在 MySQL 中操作的, 所以需要添加 MySQL 驱动

  1. 项目工程创建完成后自动在 pom.xml ⽂件中,导入 Mybatis 依赖和 MySQL 驱动依赖
<!--Mybatis 依赖包-->
<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>2.3.1</version>
</dependency>

<!--mysql驱动包-->
<dependency>
	<groupId>com.mysql</groupId>
	<artifactId>mysql-connector-j</artifactId>
	<scope>runtime</scope>
</dependency>

2.2 数据准备

  1. 创建用户表, 并创建对应的实体类 User
-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
-- 使用数据库
USE mybatis_test;
-- 创建表[用户表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `username` VARCHAR(127) NOT NULL,
    `password` VARCHAR(127) NOT NULL,
    `age` TINYINT(4) NOT NULL,
    `gender` TINYINT(4) DEFAULT '0' COMMENT '1-男 2-女 0-默认',
    `phone` VARCHAR(15) DEFAULT NULL,
    `delete_flag` TINYINT(4) DEFAULT 0 COMMENT '0-正常, 1-删除',
    `create_time` DATETIME DEFAULT NOW(),
    `update_time` DATETIME DEFAULT NOW(),
    PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
-- 添加用户信息
INSERT INTO mybatis_test.userinfo (username, `password`, age, gender, phone)
VALUES ('admin', 'admin', 18, 1, '18612340001');
INSERT INTO mybatis_test.userinfo (username, `password`, age, gender, phone)
VALUES ('zhangsan', 'zhangsan', 18, 1, '18612340002');
INSERT INTO mybatis_test.userinfo (username, `password`, age, gender, phone)
VALUES ('lisi', 'lisi', 18, 1, '18612340003');
INSERT INTO mybatis_test.userinfo (username, `password`, age, gender, phone)
VALUES ('wangwu', 'wangwu', 18, 1, '18612340004');
  1. 创建对应的实体类 UserInfo
import lombok.Data;
import java.util.Date;
@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

2.3 配置数据库连接字符串

Mybatis 中要连接数据库,需要数据库相关参数配置:

  • MySQL驱动类
  • 登录名
  • 密码
  • 数据库连接字符串
  1. application.yml 文件
# 数据库连接配置
spring:
	datasource:
		url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
		username: root
		password: root
		driver-class-name: com.mysql.cj.jdbc.Driver
  1. application.properties 文件
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#数据库连接的url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false

#连接数据库的⽤⼾名
spring.datasource.username=root

#连接数据库的密码
spring.datasource.password=root

2.4 写持久层代码

在项目中, 创建持久层接口 UserInfoMapper

在这里插入图片描述

import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserInfoMapper {
    //查询所有⽤⼾
    @Select("select username, `password`, age, gender, phone from userinfo")
    public List<UserInfo> queryAllUser();
}
  • @Mapper注解:这个注解标识了这个接口是一个 MyBatis 的 Mapper 接口,它告诉MyBatis框架要为这个接口创建一个实现类,并且这个实现类会自映射SQL语句的方法。
  • @Select注解:这个注解标识了 queryAllUser() 方法使用的查询语句,当需要执行数据库操作时,应用程序会调用 UserInfoMapper 接口中的 queryAllUser() 方法。

注意:Mybatis 的持久层接口规范⼀般都叫 XxxMapper

2.5 单元测试

2.5.1 使用 test 测试类

在创建出来的 SpringBoot 工程中,在 src 下的 test 目录下,已经自动帮我们创建好了测试类 ,我们可以直接使用这个测试类来进行测试.

import com.example.demo.mapper.UserInfoMapper;
import com.example.demo.model.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    private UserInfoMapper userInfoMapper;
    
    @Test 
    void contextLoads() {
        List<UserInfo> userInfoList = userInfoMapper.queryAllUser();
        System.out.println(userInfoList);
    }
}
  • @SpringBootTest 用于指示该类是一个 Spring Boot 应用程序的集成测试类。这个注解告诉测试运行器去加载整个 Spring 应用程序上下文,包括所有的 bean,并为测试提供一个实例化的应程序环境。
  • @Test 注解用于标识一个测试方法。当运行测试类时,它会搜索类中带有 @Test 注解的方法,并执行这些方法。

运行结果如下:

在这里插入图片描述

返回结果中, 可以看到, 只有 SQL 语句中查询的列对应的属性才有赋值

2.5.2 使用 Idea 自动生成测试类

除此之外, 也可以使用 Idea 自动生成测试类

  1. 在需要测试的Mapper接口中, 右键 -> Generate -> Test

在这里插入图片描述
2. 选择要测试的方法, 点击 OK

在这里插入图片描述

  1. 书写测试代码
import com.example.demo.model.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;
    
    @Test
    void queryAllUser() {
        List<UserInfo> userInfoList = userInfoMapper.queryAllUser();
        System.out.println(userInfoList);
    }
}

记得加 @SpringBootTest 注解, 加载 Spring 行环境

运行结果:

在这里插入图片描述

三: MyBatis 的基础操作

上面我们学习了 Mybatis 的查询操作, 接下来我们学习 MyBatis 的增, 删, 改操作,在学习这些操作之前, 我们先来学习 MyBatis 日志打印

3.1 打印日志

在 Mybatis 当中我们可以借助日志, 查看到 sql 语句的执行语句、执行传递参数以及执行结果

  1. yml 配置
mybatis:
	configuration: # 配置打印 MyBatis⽇志
		log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  1. properties 配置
#指定mybatis输出⽇志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

重新运行程序, 可以看到 SQL 执行内容, 以及传递参数和执行结果

在这里插入图片描述

  • ①: 查询语句
  • ②: 传递参数及类型
  • ③: SQL执行结果

3.2 参数传递

@Select("select username, `password`, age, gender, phone from userinfo where id= 4 ")
UserInfo queryById();

这条语句只能查找 id=4 的数据,有时候我们需要 id 的数值是动态的,我们该怎么做呢

解决方案:

  1. 在 queryById 方法中添加⼀个参数 (id),将方法中的参数,传给 SQL 语句
  2. 然后使用 #{} 的方式获取方法中的参数
@Select("select username, `password`, age, gender, phone from userinfo where id= #{id} ")
UserInfo queryById(Integer id);

如果 mapper 接口方法形参只有⼀个普通类型的参数,#{…} 里面属性名可以随便写,但如果有多个参数的话,建议和参数名保持⼀致

  1. 测试用例
@Test
void queryById() {
        UserInfo userInfo = userInfoMapper.queryById(4);
        System.out.println(userInfo);
}
  1. 运行结果

在这里插入图片描述

我们也可以通过 @Param , 设置参数的别名, 如果使用 @Param 设置别名, #{…} 里面的属性名必须和 @Param 设置的⼀样

@Select("select username, `password`, age, gender, phone from userinfo where id= #{userid} ")
UserInfo queryById(@Param("userid") Integer id);

3.3 增 (Insert)

  1. SQL 语句:
insert into userinfo (username, `password`, age, gender, phone) values ("zhaoliu","zhaoliu",19,1,"18700001234")
  1. 把 SQL 中的常量替换为动态的参数,用 Mapper 接口:
@Insert("insert into userinfo (username, `password`, age, gender, phone) values (#{username},#{password},#{age},#{gender},#{phone})")
Integer insert(UserInfo userInfo);
  1. 测试代码:
@Test
void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("zhaoliu");
        userInfo.setPassword("zhaoliu");
        userInfo.setGender(2);
        userInfo.setAge(21);
        userInfo.setPhone("18612340005");
        userInfoMapper.insert(userInfo);
}
  1. 如果设置了 @Param 属性, #{…} 需要使用参数.属性来获取
@Insert("insert into userinfo (username, `password`, age, gender, phone) values (#{userinfo.username},#{userinfo.password},#{userinfo.age},#{userinfo.gender},#{userinfo.phone})")
Integer insert(@Param("userinfo") UserInfo userInfo);

3.3.1 返回主键

Insert 语句默认返回的是受影响的行数,但有些情况下我们需要获取到新插入数据的 id ,如果想要拿到自增 id, 需要在 Mapper 接口的方法上添加⼀个 Options 的注解

@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into userinfo (username, age, gender, phone) values (#{userinfo.username},#{userinfo.age},#{userinfo.gender},#{userinfo.phone})")
Integer insert(@Param("userinfo") UserInfo userInfo);
  • @Options: 这是 Myatis 中的一个注解,用于配置一些选项以影响 SQL 语句的执行方式。
  • useGeneratedKeys = true 这个选项告诉 MyBatis 使用数据库自动生成的主键。
  • Property = “id”: 这个选项指定了用来接收生成的主键值的属性名。这个例子中,自动生成的主键值将会被赋给 UserInfo 对象中名为 id 的属性。

测试数据:

@Test
void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("zhaoliu");
        userInfo.setPassword("zhaoliu");
        userInfo.setGender(2);
        userInfo.setAge(21);
        userInfo.setPhone("18612340005");
        Integer count = userInfoMapper.insert(userInfo);
        System.out.println("添加数据条数:" +count +", 数据ID:" + userInfo.getId());
}

运行结果:

在这里插入图片描述

注意: 设置 useGeneratedKeys=true 之后, 方法返回值依然是受影响的行数, 自增 id 会设置在上述 keyProperty 指定的属性中.

3.4 删(Delete)

SQL 语句:

delete from userinfo where id=6

把 SQL 中的常量替换为动态的参数:

@Delete("delete from userinfo where id = #{id}")
void delete(Integer id);

3.5 改(Update)

SQL 语句:

update userinfo set username="zhaoliu" where id=5

把 SQL 中的常量替换为动态的参数:

@Update("update userinfo set username=#{username} where id=#{id}")
void update(UserInfo userInfo);

3.6 查(Select)

我们在上面查询时发现, 有几个字段是没有赋值的, 只有Java对象属性和数据库字段⼀模⼀样时, 才会进行赋值,接下来我们多查询⼀些数据

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
List<UserInfo> queryAllUser();
  1. 查询结果:

在这里插入图片描述

从运行结果上可以看到, 我们 SQL 语句中, 查询了 delete_flag, create_time, update_time, 但是这几个属性却没有赋值.

  1. 原因分析:

当自动映射查询结果时,MyBatis 会获取结果中返回的列名并在 Java 类中查找相同名字的属性(忽略大小写)。 这意味着如果发现了 ID 列和 id 属性,MyBatis 会将列 ID 的值赋给 id 属性,但如果名字不一样就无法进行赋值了。

在这里插入图片描述

解决办法:

  1. 起别名
  2. 结果映射
  3. 开启驼峰命名

注意:MyBatis 会根据方法的返回结果进行赋值.

  • 方法用对象 UserInfo 接收返回结果, MySQL 查询出来数据为⼀条, 就会自动赋值给对象.
  • 方法用 List< UserInfo > 接收返回结果, MySQL 查询出来数据为⼀条或多条时, 也会自动赋值给 List.
  • 但如果 MySQL 查询返回多条, 但是方法使用 UserInfo 接收, MyBatis 执行就会报错.

3.6.1 起别名

在 SQL 语句中,给列名起别名,保持别名和实体类属性名⼀样

@Select("select id, username, `password`, age, gender, phone, delete_flag as deleteFlag, " + "create_time as createTime, update_time as updateTime from userinfo")
public List<UserInfo> queryAllUser();

SQL 语句太长时, 使用加号 + 进行字符串拼接

3.6.2 结果映射

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
@Results({
	@Result(column = "delete_flag",property = "deleteFlag"),
	@Result(column = "create_time",property = "createTime"),
	@Result(column = "update_time",property = "updateTime")
})
List<UserInfo> queryAllUser();

如果其他 SQL, 也希望可以复用这个映射关系, 可以给这个 Results 定义⼀个名称

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
@Results(id = "resultMap",value = {
	@Result(column = "delete_flag",property = "deleteFlag"),
	@Result(column = "create_time",property = "createTime"),
	@Result(column = "update_time",property = "updateTime")
})
List<UserInfo> queryAllUser();

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time " + "from userinfo where id= #{userid} ")

@ResultMap(value = "resultMap")
UserInfo queryById(@Param("userid") Integer id);

使用 id 属性给该 Results 定义别名, 使用 @ResultMap 注解来复用其他定义的 ResultMap

在这里插入图片描述

3.6.3 开启驼峰命名 (推荐)

通常数据库列使用蛇形命名法进行命名,而 Java 属性⼀般遵循驼峰命名法约定,为了在这两种命名方式之间启用自动映射,需要将 mapUnderscoreToCamelCase 设置为 true。

mybatis:
	configuration:
		map-underscore-to-camel-case: true #配置驼峰⾃动转换

Java 代码不做任何处理

@Select("select id, username, `password`, age, gender, phone, delete_flag as deleteFlag, " + "create_time as createTime, update_time as updateTime from userinfo")
public List<UserInfo> queryAllUser();

添加上述配置, 运行代码:

在这里插入图片描述

字段全部进行正确赋值.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LLM 论文】CREA-ICL:利用跨语言检索来增强小语种的 ICL 能力

论文&#xff1a;From Classification to Generation: Insights into Crosslingual Retrieval Augmented ICL ⭐⭐⭐⭐ NeurIPS 2023, arXiv:2311.06595 文章目录 论文速读总结 论文速读 有很多外国语言因为其语言复杂性、标记数据集的缺乏以及数据重复等问题&#xff0c;LLM …

【讲解下如何解决一些常见的 Composer 错误】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【二等奖水平论文】2024五一数学建模C题22页保奖论文+22页matlab和13页python完整建模代码、可视图表+分解结果等(后续会更新)

一定要点击文末的卡片&#xff0c;那是资料获取的入口&#xff01; 点击链接加入群聊【2024五一数学建模】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&khoTDlhAS5N_Ffp-vucfG5WjeeJFxsWbz&authKey7oCSHS25VqSLauZ2PpiewRQ9D9PklaCxVS5X6i%2BAkDrey992f0t15…

前端高频算法

分析算法排序&#xff1a; 时间复杂度: 一个算法执行所耗费的时间。 空间复杂度: 运行完一个程序所需内存的大小。 执行效率、内存消耗、稳定性 三方面入手。 1. 排序 1.1 冒泡排序 冒泡的过程只涉及相邻数据的交换操作&#xff0c;所以它的空间复杂度为 O(1)。 为了保证…

Deep learning Part Five RNN--24.4.29

接着上期&#xff0c;CBOW模型无法解决文章内容过长的单词预测的&#xff0c;那该如何解决呢&#xff1f; 除此之外&#xff0c;根据图中5-5的左图所示&#xff0c;在CBOW模型的中间层求单词向量的和&#xff0c;这时就会出现另一个问题的&#xff0c;那就是上下文的单词的顺序…

【JVM】class文件格式,JVM加载class文件流程,JVM运行时内存区域,对象分配内存流程

这篇文章本来只是想讲一下class文件格式&#xff0c;讲着讲着越讲越多。JVM这一块吧&#xff0c;知识比较散比较多&#xff0c;如果深研究下去如死扣《深入理解Java虚拟机》&#xff0c;这本书很深很细&#xff0c;全记住是不可能的&#xff0c;其实也没必要。趁这个机会直接把…

附录6-4 黑马优购项目-分类和购物车

目录 1 分类 1.1 接口 1.2 窗口限制 1.3 选中状态样式判断 1.4 点击左侧时右侧会到顶点 1.5 源码 2 购物车 2.1 store 2.2 tabBar徽标 2.3 滑动删除 2.4 结算 2.4.1 结算前登录 2.4.2 结算功能 2.5 触发组件事件 2.6 源码 1 分类 分类最上部是…

Flutter笔记:谈Material状态属性-为什么FlatButton等旧版按钮就废弃了

Flutter笔记 谈Material状态属性-为什么FlatButton等旧版按钮就废弃了 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this artic…

免安装SQL管理工具HeidiSQL建库如何选Collation字符校对

免安装SQL管理工具HeidiSQL 文章目录 免安装SQL管理工具HeidiSQL一、安装二、建库因此&#xff0c;通常我们选择&#xff1a; 一、安装 到官方网址&#xff1a;https://www.heidisql.com/ 下载后按不同版本安装或解压&#xff0c;运行目录中的heidisql应用程序。 该工具可以对…

「生存即赚」链接现实与游戏,打造3T平台生态

当前&#xff0c;在线角色扮演游戏&#xff08;RPG&#xff09;在区块链游戏市场中正迅速崛起&#xff0c;成为新宠。随着区块链技术的不断进步&#xff0c;众多游戏开发者纷纷将其游戏项目引入区块链领域&#xff0c;以利用这一新兴技术实现商业价值的最大化。在这一趋势中&am…

加州大学欧文分校英语中级语法专项课程02:Adjectives and Adjective Clauses 学习笔记

Adjectives and Adjective Clauses course certificate 本文是 https://www.coursera.org/learn/adjective-clauses 这门课的学习笔记。 文章目录 Adjectives and Adjective ClausesWeek 01: Adjectives and Adjective PhrasesLearning Objectives Adjectives Introduction Le…

基于Java的智慧社团综合管理系统的设计与实现(论文+源码)_kaic

摘 要 随着校园文化的不断丰富&#xff0c;大学里各种社团越来越多&#xff0c;社团活动也越来越频繁&#xff0c;社员也越来越多&#xff0c;而且大学生退社、入社比较频繁&#xff0c;社团管理就显得非常繁琐而又复杂,如果采用人工管理,对管理员来说将是一件很头疼的事情。设…

5个本地流畅运行大模型的免费工具

大家好&#xff0c;随着大型语言模型&#xff08;LLM&#xff09;驱动的聊天机器人逐渐普及&#xff0c;给人们的工作和生活带来了前所未有的便利。然而&#xff0c;这种便捷性背后潜藏着个人隐私信息被泄露的风险&#xff0c;例如AI公司会收集聊天记录和元数据来优化模型&…

【Vulhub靶场】Nginx 漏洞复现

Nginx 漏洞复现 一、Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09;1、影响版本2、漏洞原理3、漏洞复现 二、Nginx 解析漏洞1、版本信息&#xff1a;2、漏洞详情3、漏洞复现 一、Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09; 1、影响版本 Nginx …

mysql 数据转excel文件

mysql 数据转excel文件 缘由 为售后拉取数据&#xff0c;用navicat太墨迹了&#xff0c;用python写一个main方法跑一下&#xff1b; 1.抽取共同方法&#xff0c;封装成传入mysql&#xff0c;直接下载成excel&#xff1b; 2.写入所有sql语句&#xff0c;传入参数&#xff1b; 代…

2024-05-02 商业分析-杭州小万科技-商业模式分析

摘要: 对杭州小万科技的商业模式进行分析,以对其做出客观的评估。 杭州小万科技的资料: 杭州小万科技有限公司 - 企知道 (qizhidao.com) 杭州小万科技有限公司网站备案查询 - 天眼查 (tianyancha.com) 杭州小万科技有限公司 - 爱企查 (baidu.com) ​ 2023年年报:

Android手写自己的路由SDK

实现自己的路由框架 ​ 在较大型的Android app中常会用到组件化技术&#xff0c;针对不同的业务/基础功能对模块进行划分&#xff0c;从上到下为壳工程、业务模块、基础模块。其中业务模块依赖基础模块&#xff0c;壳工程依赖业务模块。同级的横向模块&#xff08;比如多个业务…

BeanFactory 源码浅析

BeanFactory 功能介绍 BeanFactory 是核心容器&#xff0c;负责管理 Bean 对象 BeanFactory 接口的功能只有一个 getBean() 方法BeanFactory 的实现类&#xff08;DefaultListableBeanFactory&#xff09;包含&#xff1a;控制反转、基本的依赖注入、Bean 生命周期的各种功能…

【Python】函数设计

1.联系函数的设计 2.找质数 3.找因子 4.判断水仙花数 5.斐波拉契数列递归调用&#xff0c;并用数组存储已计算过的数&#xff0c;减少重复计算 1、计算利息和本息 编写两个函数分别按单利和复利计算利息,根据本金、年利率、存款年限得到本息和和利息。调用这两个函数计算1…

【算法刷题日志】吸氧羊的StarryCoding之旅 - 贡献法计算

题目链接&#xff1a;https://www.starrycoding.com/problem/3 题目描述 吸氧羊终于注册了一个StarryCoding账号&#xff01;&#xff08;她很开心&#xff09; 但是吸氧羊忘记了它的密码&#xff0c;她想起你是计算机大师&#xff0c;于是就来请教你。 她虽然不记得密码了…