时长
1h
方式
腾讯会议
项目
- 介绍项目
Spring八股
Spring得狠狠补
- SpringBoot常用注解
- Spring事务详解 好好看这篇Spring 事务详解 | JavaGuide
- SpringBoot配置格式
- SpringBoot如何集成Redis
- @AutoWired和@Resource注解
- SpringBoot自动装配机制
- SpringBoot实现Bean装配
MySQL
说的不够流畅
- MySQL建表,如何优化索引
- 唯一索引可以为空么?
- InnodDB的底层结构(B+树、B树、哈希表都讲讲)
- MySQL隔离级别,对应问题
- MySQL索引下推
- MySQL中客户端与服务端
- MySQL主从复制(半同步复制)
- Redis和MySQL缓存一致性
- MySQL锁
- MySQL如何实现乐观锁
- 自己补充的问题
- MySQL 怎么保证原子性的?
多线程
- 如何实现多线程
- 线程池参数
- 线程池执行流程
- 拒绝策略
- 有界队列 无界队列
- HashMap(1.8之后的改动)
- ConcurrentHashMap原理(分段锁)
- 有序的Map
- SpringBoot的单例模式
- 双重校验锁(Double-Checked Locking,DCL)
- synchronized Lock Reentrantlock
其他
- 项目中常用的数据结构
下面是答案,不准确的地方请各位指正:
SpringBoot常用注解:
- 包含了@Configuration、@EnableAutoConfiguration、@ComponentScan三个注解的集合。通过这个注解可以自动配置Spring容器中的Bean,并启动程序。
- @RestController: 标记在控制器类上,表示该类中的所有处理方法都会返回HTTP响应体内容。
- @GetMapping和@PostMapping:用于映射HTTP请求到特定的方法上。
- @AutoWired:用于自动装配Bean,即Spring容器会自动查找并注入与字段类型匹配的Bean。
- @Service:声明一个类为Spring托管的服务组件,一般用于实现业务逻辑。
- @Configuration:表示当前类是一个配置类,Spring Boot会从该类中加载Bean定义。
- @Value:用于注入属性值,可以从配置文件中读取配置。
Spring事务详解
**事务是逻辑上的一组操作,要么都执行,要么都不执行。**事务能否生效数据库引擎是否支持事务是关键。比如常用的 MySQL 数据库默认使用支持事务的 innodb引擎。但是,如果把数据库引擎变为 myisam,那么程序也就不再支持事务了!
Spring支持两种方式的事务管理
- 编程式事务管理:TransactionTemplate 或者 TransactionManager手动管理事务。
- 声明式事务管理:推荐使用,实际是通过AOP实现(基于@Transactional的全注解方式使用最多)
Spring事务管理接口介绍:
- PlatfromTransactionManager:(平台)事务管理器,Spring事务策略的核心。
- Transactionfinition:事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)
- TransactionStatus:事务运行状态。
@Transactional 事务注解原理
-
@Transactional的工作机制是基于AOP实现的,AOP又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用了JDK的动态代理;如果目标对象没有实现了接口,会使用CGLIB动态代理。
-
如果一个类或者一个类中的public方法上被标注@Transactional注解的话,Spring容器就会在启动时候为其创建一个代理类。在调用被@Transactional注解的public方法的时候,实际调用的是TransactionInterceptor类中的invoke()方法。这个方法的作用就是在目标方法之前开始事务,方法执行过程中如果遇到异常的时候回滚事务,方法调用完成之后提交事务。
SpringBoot配置格式
- application.properties: 这是最常用的配置文件,使用简单的键值对形式来配置各种属性。
- application.yml 或 application.yaml: YAML 是一种更简洁、易读的配置文件格式,支持层级结构和列表等复杂数据结构。在Spring Boot中可以这样配置:
spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: root password: password transaction: default-timeout: 30s # 时间单位可以根据需要指定,如's'为秒 logging: level: org.springframework.web: DEBUG
SpringBoot如何集成Redis
使用Jedis。
- 添加依赖:首先需要在pom.xml文件中添加Jedis和Spring Data Redis的依赖。
- 配置Redis: 在application.properties或者application.yml中配置Redis服务器的详细信息(端口)。
- 配置JedisConnectionFactory:可以配置一个JedisConnectionFactory bean来指定使用Jedis作为Redis客户端。
- SpringBoot提供了一个RedisTemplate或者StringRedisTemplate bean, 你可以在你的服务器或组件中注入并使用它。
@AutoWired和@Resource注解
AutoWired属于Spring内置的注解,默认的注入方式为byType(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入Bean。但存在问题,当一个接口存在多个实现类的话,根据类型进行匹配这种方式就无法注入对象,因为这个时候Spring会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。
@Resource属于JDK提供的注解,默认类型是根据名称注入。如果无法通过名称匹配到对应的Bean时,注入方式就会变成根据类型注入。
区别:
- @AutoWired是Spring提供的注解,@Resource是JDK提供的注解。
- 注入方式不同。
- 当一个接口下存在多个实现类的情况下,@AutoWired和@Resource都需要通过名称才能正确匹配到对应的Bean。前者通过Qualifier注解,后者通过name属性。
SpringBoot 自动装配原理
自动装配可以实现通过Spring Boot的全局配置文件application.yml实现项目配置。 在Spring Boot中,我们直接引入一个starter即可,引入starter之后,我们通过少量注解和一些简单的配置就能使用使用第三方组件提供的功能。 @SpringBootApplication是@Configuration、@EnableAutoConfiguration、 @ComponentScan的集合。 @EnableAutoConfiguration:启用Sprint Boot的自动配置机制。 @Configuration:允许在上下文中注册额外的bean或导入其他配置类。 @ComponentScan:扫描被@Component(@Service、@Controller)注解的bean。注解默认会扫描启动类所在的包下所有的类。
@EnableAutoConfiguration:实现自动装配的核心注解
EnableAutoConfiguration 只是一个简单地注解,自动装配核心功能的实现是通过AutoConfigurationImportSelector类。
AutoConfigurationImportSelector类实现了ImportSelector接口,也就实现了接口中的selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类中需要被加载到IoC容器中。
SpringBoot自动装配步骤
- 识别启动类:启动类通常是一个带有@SpringBootApplication注解的类。
- 解析注解:三个注解启动。
- 执行自动装配
- 加载配置:读取application.yml之类的配置文件,并解析配置信息。这些配置信息被用于创建和配置Bean。
- 创建和装配Bean:包括创建第三方组件的Bean
SpringBoot实现Bean装
- 通过注解装配Bean
- @Component:通用注解,用于声明一个Bean。
- @Service: 用于业务逻辑层的Bean。
- @Repository: 用于数据访问层的Bean,如DAO。
- @Controller和@RestController: 用于Web层的Bean。
- 使用@AutoWired装配依赖 一般在构造器中使用@AutoWired注解。
- 使用Java配置类装配Bean 创建一个配置类,使用@Bean注解来定义Bean。
- 使用@Import导入配置
唯一索引可以为空么?
MySQL唯一索引允许有空值,但一个索引列最多有一个空值。(即不能有多行的该索引段都是控制)。
唯一索引确保索引列的值是唯一的。一张表可以有多个唯一索引。
InnodDB的底层结构(B+树)
MySQL索引下推
在没有索引下推的情况下,MySQL会首先使用索引来定位满足满足where子句中部分条件的行,然后返回这些行的主键给服务器层。服务器层再根据这些主键去表中获取完整的行数据,并检查它们是否满足where子句中的其他条件。
使用索引下推后,MySQL会将where子句中的部分条件(即涉及到索引列的条件)下推到存储引擎层,这样存储引擎层在扫描索引时就能直接过滤掉不满足条件的行。从而只返回满足所有条件的行的主键给服务器层。
MySQL主从复制(半同步复制)
- 安装半同步复制插件
- 配置主服务器
- 配置从服务器
- 设置复制用户并启动复制
- 验证复制状态
MySQL中客户端与服务端
Redis和MySQL缓存一致性
- 先更新数据库,再删除缓存
- 先删除Redis缓存再更新MySQL
- 缓存失效策略
- 使用Redis的过期时间(TTL)配合MySQL的binlog监听,每当MySQL有数据更新时,设置相关Redis键的TTL为一个较短的时间,在这个时间内如果缓存被访问则重新从数据库加载。
MySQL锁
-
表级锁:MyISAM仅支持表级锁。粒度较大。
-
行级锁:InnoDB 的行锁是针对索引字段加的锁,表级锁是针对非索引字段加的锁。
InnoDB支持三种行锁
- 记录锁: 属于单个行记录上的锁。
- 间隙锁:锁定一个范围,不包括记录本身。
- 临键锁(Next-Key Lock):前两者的一个结合,锁定一个范围,包含记录本身。主要目的是解决幻读问题。记录锁只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁。
不管表级锁还是行级锁,都存在共享锁和排他锁: 共享锁: 事务在读取记录的时候获取锁,允许多个事务同时获取。 排他锁: 事务在修改记录的时候获取排他锁,不允许多个事务同时获取。
意向锁是表级锁,用来判断是否可以对某个表使用表锁。分为:
- 意向共享锁:事务有意向表中的某些记录加共享锁,加共享锁前必须获取该表的意向共享锁。
- 意向排他锁:事务有意向表中的某些记录加排他锁,加排他锁之前必须获取该表的意向排他锁。
意向锁之间是兼容的。
MySQL如何实现乐观锁
在MySQL中实现乐观锁主要通过数据版本(version)控制的方式,即为表中的记录增加一个版本号字段。当读取数据时,同时获取当前版本号;更新数据时,则需要比较数据库中该记录的版本号是否与之前读取的一致,只有当版本号一致的情况下才允许更新,否则认为有并发修改发生并拒绝此次更新请求。
乐观锁和悲观锁
乐观锁:假设通常情况下不会发生并发冲突,所以不会预先锁定数据。当更新时发现版本号不一致,则返回更新失败。适合读多写少。 悲观锁:假设会发生冲突,当事务读取某一行时,立即获取对该行的锁。当一个事务对某条记录进行更新或删除前,先尝试获取该记录的排他锁(Exclusive Lock),直到事务结束才释放锁。
MySQL 怎么保证原子性的?
-
事务日志(Transaction log):
- MySQL使用事务日志(InnoDB引擎使用redo log和undo log)来确保原子性。在事务执行过程中,所有的修改操作先被记录到事务日志中,而不是直接写入数据文件。
- redo log(重做日志)用于崩溃恢复,确保即使在数据库服务器突然宕机时,也能通过重播日志将已提交但未持久化到磁盘的数据重新写入,从而保证事务的持久性和原子性。
- undo log(撤销日志)用于事务回滚,当事务需要回滚时,MySQL可以通过undo log找到事务修改前的状态,并进行还原,确保事务的原子性。