Spring 面试题答案
1. 什么是 Spring
Spring 是一个轻量级的开源 Java 框架,用于构建企业级应用。它提供了一套全面的基础设施支持,包括:
- IoC(控制反转):管理对象创建和依赖注入。
- AOP(面向切面编程):实现横切关注点(如日志、事务)的模块化。
- 数据访问:简化 JDBC、ORM 框架集成。
- 事务管理:支持声明式和编程式事务。
- Web 开发:提供 Spring MVC 框架。
- 集成能力:支持消息队列、远程调用等。
2. 项目中为什么使用 Spring 框架
- 解耦和模块化:IoC 容器管理对象依赖,降低耦合。
- AOP 支持:统一处理日志、事务等横切逻辑。
- 丰富的生态:集成数据访问、Web、安全等模块。
- 简化开发:提供模板类(如
JdbcTemplate
)减少样板代码。 - 事务管理:声明式事务简化数据库操作。
- 测试友好:支持依赖注入,便于单元测试。
3. @Autowired 和 @Resource 的区别
特性 | @Autowired (Spring) | @Resource (JSR-250) |
---|---|---|
来源 | Spring 框架 | Java 标准 (javax.annotation) |
默认装配方式 | 按类型(byType) | 按名称(byName) |
名称指定 | 需配合 @Qualifier 注解 | 直接通过 name 属性指定 |
适用范围 | 字段、构造器、方法 | 字段、Setter 方法 |
4. 依赖注入的方式
- 构造器注入:
通过构造器传递依赖,确保对象不可变。public class UserService { private final UserRepository repo; public UserService(UserRepository repo) { this.repo = repo; } }
- Setter 注入:
通过 Setter 方法注入,灵活性高。public class UserService { private UserRepository repo; public void setRepo(UserRepository repo) { this.repo = repo; } }
- 字段注入:
直接注入字段,简单但破坏封装性(不推荐)。public class UserService { @Autowired private UserRepository repo; }
5. 讲一下什么是 Spring
Spring 的核心是 IoC 容器 和 AOP:
- IoC 容器:管理 Bean 的生命周期和依赖关系,通过依赖注入实现解耦。
- AOP:将横切逻辑(如事务、日志)与业务代码分离。
- 扩展模块:Spring MVC(Web)、Spring Data(数据访问)、Spring Security(安全)等。
6. 对 Spring MVC 的理解
Spring MVC 是基于 MVC 模式的 Web 框架:
- 流程:
- 用户请求 →
DispatcherServlet
(前端控制器)。 HandlerMapping
匹配请求到Controller
。Controller
处理请求,返回ModelAndView
。ViewResolver
解析视图 → 渲染响应。
- 用户请求 →
- 优点:配置灵活、支持 REST、集成验证和数据绑定。
7. Spring MVC 常用注解
注解 | 作用 |
---|---|
@Controller | 标记类为控制器 |
@RequestMapping | 映射 URL 到方法 |
@RequestParam | 绑定请求参数到方法参数 |
@PathVariable | 绑定 URL 模板变量 |
@ResponseBody | 返回 JSON/XML 数据 |
@RequestBody | 将请求体解析为对象 |
@ModelAttribute | 绑定请求参数到模型对象 |
8. 对 Spring AOP 的理解
- 核心概念:
- 切面(Aspect):封装横切逻辑的模块(如日志切面)。
- 通知(Advice):切面在特定连接点的动作(如
@Before
)。 - 切点(Pointcut):定义哪些连接点触发通知(如
execution(* save*(..))
)。
- 实现原理:动态代理(JDK 代理或 CGLIB 字节码增强)。
9. Spring AOP 和 AspectJ AOP 的区别
特性 | Spring AOP | AspectJ |
---|---|---|
实现方式 | 动态代理 | 编译时/加载时织入 |
连接点支持 | 仅方法执行 | 方法、构造器、字段等 |
性能 | 运行时代理,较低 | 编译期优化,高性能 |
依赖 | 轻量级,无需额外编译器 | 需 AspectJ 编译器或织入器 |
10. 关注点、横切关注点、通知
- 关注点(Concern):软件模块的核心功能(如用户管理)。
- 横切关注点(Cross-cutting Concern):跨越多个模块的功能(如日志、事务)。
- 通知(Advice):切面在连接点执行的动作,分五种类型:
@Before
:方法执行前。@After
:方法执行后(无论是否异常)。@AfterReturning
:方法正常返回后。@AfterThrowing
:方法抛出异常后。@Around
:包裹方法执行(可控制是否执行方法)。
11. 对 Spring IoC 的理解
IoC(控制反转)将对象创建和依赖管理的控制权从代码转移到 Spring 容器:
- 核心机制:依赖注入(DI),通过构造器、Setter 或字段注入依赖。
- 优点:解耦、易于测试、集中管理对象生命周期。
12. 基于 XML 注入 Bean 的方式
- Setter 注入:
<bean id="userService" class="com.example.UserService"> <property name="userRepo" ref="userRepo"/> </bean>
- 构造器注入:
<bean id="userService" class="com.example.UserService"> <constructor-arg ref="userRepo"/> </bean>
- 工厂方法注入:
<bean id="userRepo" class="com.example.UserRepoFactory" factory-method="createRepo"/>
13. Spring Bean 的生命周期
- 实例化(调用构造器)。
- 属性赋值(注入依赖)。
- 调用
BeanNameAware.setBeanName()
。 - 调用
BeanFactoryAware.setBeanFactory()
。 - 调用
ApplicationContextAware.setApplicationContext()
。 - 前置处理:
BeanPostProcessor.postProcessBeforeInitialization()
。 - 初始化:调用
InitializingBean.afterPropertiesSet()
或自定义init-method
。 - 后置处理:
BeanPostProcessor.postProcessAfterInitialization()
。 - Bean 可用。
- 销毁:调用
DisposableBean.destroy()
或自定义destroy-method
。
14. Bean 的作用域
作用域 | 描述 |
---|---|
singleton (默认) | 容器中仅一个实例 |
prototype | 每次请求创建新实例 |
request | 每个 HTTP 请求一个实例(Web 应用) |
session | 每个 HTTP 会话一个实例(Web 应用) |
application | 整个 Web 应用共享一个实例(ServletContext) |
15. Spring 中的设计模式
- 工厂模式:
BeanFactory
创建对象。 - 单例模式:默认作用域的 Bean 是单例。
- 代理模式:AOP 动态代理。
- 模板方法:
JdbcTemplate
封装数据库操作。 - 观察者模式:事件监听机制(
ApplicationEvent
)。 - 适配器模式:
HandlerAdapter
处理多种 Controller。
16. ApplicationContext 和 BeanFactory 的区别
特性 | BeanFactory | ApplicationContext |
---|---|---|
功能 | 基础 IoC 容器 | 扩展 BeanFactory,支持更多功能 |
加载时机 | 延迟加载(按需初始化 Bean) | 启动时预加载所有单例 Bean |
企业级支持 | 不支持 AOP、事件等 | 支持 AOP、事件、国际化等 |
实现类 | XmlBeanFactory | ClassPathXmlApplicationContext |
17. 单例 Bean 的线程安全
- 默认不安全:单例 Bean 被多线程共享,若包含状态(成员变量)可能引发并发问题。
- 解决方案:
- 使用无状态 Bean(无成员变量)。
- 用
ThreadLocal
保存线程私有数据。 - 改为
prototype
作用域(每次请求新实例)。 - 对方法加锁(如
synchronized
)。
18. Spring 解决循环依赖
通过 三级缓存 解决:
- 一级缓存(
singletonObjects
):存放完全初始化的 Bean。 - 二级缓存(
earlySingletonObjects
):存放提前暴露的 Bean(未初始化)。 - 三级缓存(
singletonFactories
):存放 Bean 工厂(用于生成半成品 Bean)。
流程示例(A 依赖 B,B 依赖 A):
- 创建 A → 实例化 A → 将 A 的工厂放入三级缓存。
- 注入 B → 创建 B → 实例化 B → 将 B 的工厂放入三级缓存。
- 注入 A → 从三级缓存获取 A 的半成品 → 将 A 放入二级缓存。
- 完成 B 的初始化 → 将 B 放入一级缓存。
- 完成 A 的初始化 → 将 A 放入一级缓存。
限制:仅支持单例作用域且通过 Setter/字段注入的循环依赖。
19. 事务隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 | 描述 |
---|---|---|---|---|
READ_UNCOMMITTED | ✓ | ✓ | ✓ | 可读取未提交数据 |
READ_COMMITTED (默认) | ✗ | ✓ | ✓ | 只能读取已提交数据 |
REPEATABLE_READ | ✗ | ✗ | ✓ | 同一事务多次读取结果一致 |
SERIALIZABLE | ✗ | ✗ | ✗ | 串行执行事务,完全隔离 |
20. 事务传播行为
传播行为 | 描述 |
---|---|
REQUIRED (默认) | 当前有事务则加入,否则新建事务 |
SUPPORTS | 当前有事务则加入,否则非事务执行 |
MANDATORY | 当前有事务则加入,否则抛异常 |
REQUIRES_NEW | 新建事务,挂起当前事务(独立提交回滚) |
NOT_SUPPORTED | 非事务执行,挂起当前事务 |
NEVER | 非事务执行,当前有事务则抛异常 |
NESTED | 嵌套事务(外部事务回滚会导致嵌套事务回滚) |
Spring Boot 面试题答案
1. 为什么用 Spring Boot
- 快速启动:内嵌 Tomcat/Jetty,无需部署 WAR。
- 自动配置:根据依赖自动配置 Bean(如添加
spring-boot-starter-data-jpa
自动配置 JPA)。 - 简化依赖:Starter POMs 聚合常用依赖。
- 生产就绪:提供监控端点(如
/actuator/health
)。 - 零配置:约定优于配置(如默认配置文件
application.properties
)。
2. 核心注解及组成
核心注解:@SpringBootApplication
组成:
@SpringBootConfiguration
:标记配置类(继承@Configuration
)。@EnableAutoConfiguration
:启用自动配置。@ComponentScan
:扫描当前包及子包的组件。
3. 运行 Spring Boot 的方式
- IDE 运行:直接启动
main
方法。 - Maven 插件:
mvn spring-boot:run
。 - 打包运行:
mvn package
→java -jar app.jar
。 - Gradle 插件:
gradle bootRun
。
4. Starters 的理解
- 作用:简化 Maven/Gradle 依赖,提供“开箱即用”功能。
- 命名规则:
spring-boot-starter-{功能}
(如spring-boot-starter-web
)。 - 原理:Starter 包含自动配置类和依赖管理,无需手动配置版本。
5. 启动时运行特定代码
- 实现
ApplicationRunner
或CommandLineRunner
:@Component public class InitRunner implements ApplicationRunner { @Override public void run(Application args) { // 启动时执行 } }
- 监听事件:
@EventListener(ApplicationStartedEvent.class) public void onStart() { // 应用启动后执行 }
6. 需要独立容器运行吗
不需要:Spring Boot 内嵌 Tomcat/Jetty/Undertow,可直接运行 JAR 文件。
7. 监视器是什么
Spring Boot Actuator 提供生产监控端点:
- 常用端点:
/health
(健康检查)、/info
(应用信息)、/metrics
(性能指标)。 - 启用方式:添加依赖
spring-boot-starter-actuator
。
8. 实现异常处理
- 全局异常处理器:
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception e) { return ResponseEntity.status(500).body("Error: " + e.getMessage()); } }
- 自定义错误页面:在
src/main/resources/static/error/
添加404.html
、500.html
。
9. 热部署方式
- Spring Boot DevTools:
添加依赖,修改代码后自动重启(不适用于生产环境)。 - JRebel:商业工具,实时重载类。
- IDE 热部署:如 IntelliJ IDEA 的
Build Project Automatically
。
10. 配置加载顺序
优先级从高到低:
- 命令行参数(
--server.port=8081
)。 - JNDI 属性。
- Java 系统属性(
System.getProperties()
)。 - 操作系统环境变量。
- 外部配置文件(如
application-{profile}.yml
)。 - 内部配置文件(
application.properties
)。 @PropertySource
注解。
11. 核心配置文件及区别
application.properties
/application.yml
:主配置文件。bootstrap.properties
/bootstrap.yml
:
优先级更高,用于加载外部配置(如 Spring Cloud Config Server)。
12. 集成 Spring Boot 和 ActiveMQ
- 添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency>
- 配置连接:
spring.activemq.broker-url=tcp://localhost:61616
- 发送消息:
@Autowired private JmsTemplate jmsTemplate; jmsTemplate.convertAndSend("queue.test", "Hello");
- 接收消息:
@JmsListener(destination = "queue.test") public void receive(String message) { ... }
13. 约定优于配置的理解
- 核心思想:减少决策点,提供默认行为。
- 示例:
- 默认配置文件:
application.properties
。 - 静态资源路径:
src/main/resources/static
。 - 无需配置视图解析器,默认查找
templates/
目录。
- 默认配置文件:
14. 解决跨域问题
- 全局配置:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST"); } }
- 局部注解:在 Controller 方法上加
@CrossOrigin
。
15. 自动装配原理
- 启动类注解:
@SpringBootApplication
→@EnableAutoConfiguration
。 - 加载配置:通过
spring.factories
加载AutoConfiguration
类。 - 条件装配:
@ConditionalOnClass
、@ConditionalOnProperty
等决定是否生效。 - 创建 Bean:自动配置类中定义
@Bean
方法。
16. 自动装配机制原理
同第 15 题(问题重复)。
JVM 面试题答案
1. 类加载与卸载
- 加载:
- 通过类名获取二进制字节流。
- 转化为方法区的运行时数据结构。
- 生成
Class
对象。
- 卸载:
满足条件时卸载类:- 所有实例已被 GC。
- 加载该类的
ClassLoader
已被 GC。 - 对应的
Class
对象未被引用。
2. JVM 内存模型
区域 | 作用 |
---|---|
程序计数器 | 当前线程执行的字节码行号 |
虚拟机栈 | 存储栈帧(局部变量、操作数栈) |
本地方法栈 | 执行 Native 方法 |
堆 | 存储对象实例(GC 主要区域) |
方法区(元空间) | 存储类信息、常量、静态变量 |
3. 堆和栈的区别
特性 | 堆 | 栈 |
---|---|---|
存储内容 | 对象实例 | 局部变量、栈帧 |
线程共享 | 是 | 否(线程私有) |
生命周期 | 对象存活期 | 方法调用期 |
异常 | OutOfMemoryError | StackOverflowError |
4. 触发 Full GC 的场景
- 老年代空间不足。
- 方法区(元空间)不足。
- 调用
System.gc()
(不保证立即执行)。 - Minor GC 后晋升到老年代的对象平均大小 > 老年代剩余空间。
5. Java 虚拟机与平台无关性
- Java 虚拟机(JVM):执行 Java 字节码的虚拟计算机。
- 平台无关性:Java 源码编译为字节码(.class),由 JVM 解释执行。不同平台有对应的 JVM 实现,屏蔽底层差异。
6. 对象分配原则
- 对象优先在 Eden 区分配:新对象分配在新生代 Eden 区。
- 大对象直接进老年代:避免在 Eden 区复制(如大数组)。
- 长期存活对象进老年代:对象年龄计数器 > 阈值(默认 15)。
- 空间分配担保:Minor GC 前检查老年代剩余空间是否足够。
7. Class 文件加载机制
- 步骤:加载 → 验证 → 准备 → 解析 → 初始化。
- 类加载器:
- 启动类加载器(Bootstrap):加载
JAVA_HOME/lib
下的类。 - 扩展类加载器(Extension):加载
JAVA_HOME/lib/ext
下的类。 - 应用类加载器(Application):加载用户类路径(ClassPath)的类。
- 启动类加载器(Bootstrap):加载
8. Java 对象创建过程
- 类加载检查:检查类是否已加载。
- 分配内存:在堆中划分对象空间(指针碰撞或空闲列表)。
- 初始化零值:成员变量赋默认值(0、false、null)。
- 设置对象头:存储哈希码、GC 分代年龄等信息。
- 执行构造器:调用
<init>
方法初始化对象。
9. 判断对象可回收
- 可达性分析法:从 GC Roots 开始搜索,不可达的对象可回收。
- GC Roots 包括:
- 虚拟机栈中引用的对象。
- 方法区中静态属性引用的对象。
- 方法区中常量引用的对象。
- Native 方法引用的对象。
10. 永久代中的垃圾回收
- JDK 8 前:永久代(方法区实现)会进行垃圾回收(回收废弃常量和无用的类)。
- JDK 8+:永久代被元空间(Metaspace)取代,垃圾回收由元空间管理器处理。
11. 调优命令
命令 | 作用 |
---|---|
jps | 查看 Java 进程 ID |
jstat | 监控堆内存和 GC 情况 |
jinfo | 查看和修改 JVM 参数 |
jmap | 生成堆转储快照(Heap Dump) |
jstack | 生成线程快照(Thread Dump) |
12. 调优工具
工具 | 作用 |
---|---|
JConsole | 监控内存、线程、类等 |
VisualVM | 分析内存、线程、CPU |
MAT | 分析 Heap Dump 文件 |
Arthas | 线上诊断工具 |
13. Minor GC 和 Full GC 发生时机
- Minor GC:当 Eden 区满时触发。
- Full GC:
- 老年代空间不足。
- 方法区空间不足。
- 显式调用
System.gc()
。
MySQL 面试题答案
1. 数据库三范式
- 第一范式(1NF):字段原子性(不可再分)。
- 第二范式(2NF):消除部分依赖(非主键字段完全依赖主键)。
- 第三范式(3NF):消除传递依赖(非主键字段间无依赖)。
2. MySQL 数据库引擎
引擎 | 特性 |
---|---|
InnoDB | 支持事务、行锁、外键(默认引擎) |
MyISAM | 不支持事务,表锁,全文索引 |
Memory | 数据存内存,重启丢失 |
Archive | 高压缩比,适合日志存储 |
3. InnoDB 和 MyISAM 的区别
特性 | InnoDB | MyISAM |
---|---|---|
事务 | 支持 | 不支持 |
锁粒度 | 行锁 | 表锁 |
外键 | 支持 | 不支持 |
崩溃恢复 | 支持 | 不支持 |
存储文件 | .ibd (数据+索引) | .frm (表结构) + .MYD (数据) + .MYI (索引) |
4. 数据库事务
- ACID 特性:
- 原子性(A):事务要么全成功,要么全失败。
- 一致性(C):事务前后数据库状态一致。
- 隔离性(I):并发事务互不干扰。
- 持久性(D):事务提交后数据永久保存。
- 实现:通过日志(Redo Log、Undo Log)和锁机制。
5. 索引是什么
- 定义:帮助数据库高效查询的数据结构(如 B+Tree)。
- 优点:加速查询。
- 缺点:占用空间,降低写操作速度。
6. SQL 优化手段
- 避免
SELECT *
,只取需要的字段。 - 使用索引覆盖查询(避免回表)。
- 避免在索引列上使用函数或计算。
- 用
JOIN
代替子查询。 - 分页优化:避免
OFFSET
过大(使用WHERE id > ?
)。 - 避免
OR
条件(改用UNION
)。
7. DROP、DELETE、TRUNCATE 的区别
操作 | 类型 | 可回滚 | 重置自增 ID | 删除内容 |
---|---|---|---|---|
DELETE | DML | 是 | 否 | 数据(可带条件) |
TRUNCATE | DDL | 否 | 是 | 所有数据(不可带条件) |
DROP | DDL | 否 | 是 | 表结构 + 数据 |
8. 视图
- 定义:虚拟表,基于 SQL 查询结果。
- 优点:
- 简化复杂查询。
- 隐藏敏感字段。
- 权限控制(只暴露视图)。
9. 并发事务问题
- 脏读:读到未提交的数据。
- 不可重复读:同一事务内多次读取结果不同(数据被修改)。
- 幻读:同一事务内多次读取记录数不同(数据被增删)。
10. 内连接、左外连接、右外连接
- 内连接(INNER JOIN):返回两表匹配的行。
- 左外连接(LEFT JOIN):返回左表所有行 + 右表匹配行(不匹配为 NULL)。
- 右外连接(RIGHT JOIN):返回右表所有行 + 左表匹配行(不匹配为 NULL)。
11. 事务隔离级别及默认
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ_UNCOMMITTED | ✓ | ✓ | ✓ |
READ_COMMITTED | ✗ | ✓ | ✓ |
REPEATABLE_READ (默认) | ✗ | ✗ | ✓ |
SERIALIZABLE | ✗ | ✗ | ✗ |
12. 大表优化
- 限定数据范围:禁止不带条件的查询。
- 读写分离:主库写,从库读。
- 垂直分区:按列拆分表(如冷热数据分离)。
- 水平分区:按行拆分表(如按时间分表)。
13. 分库分表后 ID 主键处理
- Snowflake 算法:生成分布式 ID(时间戳 + 机器 ID + 序列号)。
- 数据库自增 ID + 步长:
分库 1:起始值 1,步长 2 → ID: 1, 3, 5…
分库 2:起始值 2,步长 2 → ID: 2, 4, 6… - Redis 自增:利用
INCR
命令生成全局 ID。
14. 查询 SQL 执行流程
- 连接器:管理连接,验证权限。
- 查询缓存:命中缓存直接返回(MySQL 8.0 已移除)。
- 解析器:词法分析 → 语法分析 → 解析树。
- 优化器:生成执行计划,选择索引。
- 执行器:调用存储引擎接口执行查询。
- 存储引擎:读取数据返回。
15. 索引优缺点
- 优点:加速查询、唯一约束。
- 缺点:占用空间、降低写速度、维护成本高。
16. VARCHAR 和 CHAR 的区别
类型 | 长度 | 存储方式 | 示例 varchar(30) |
---|---|---|---|
CHAR | 固定 | 不足长度补空格 | 固定 30 字符 |
VARCHAR | 可变 | 长度前缀 + 实际数据 | 最大 30 字符,实际长度可变 |
17. INT(11) 的含义
INT(11)
:显示宽度为 11,不影响存储范围(INT
固定 4 字节)。- 用途:配合
ZEROFILL
时用 0 填充(如INT(5)
存储 42 → 显示00042
)。
18. 索引实现与优化
- 实现原理:B+Tree(多路平衡搜索树)。
- 索引类型:
主键索引、唯一索引、普通索引、组合索引、全文索引。 - 优化建议:
- 避免在索引列上计算。
- 最左前缀原则(组合索引)。
- 选择区分度高的列建索引。
- 避免冗余索引。
MyBatis 面试题答案
1. 什么是 MyBatis
- 半 ORM 框架,封装 JDBC 操作。
- 通过 XML 或注解配置 SQL 映射。
- 支持动态 SQL、缓存、插件扩展。
2. MyBatis 优缺点
- 优点:
- SQL 灵活可控。
- 减少 JDBC 样板代码。
- 与 Spring 集成方便。
- 缺点:
- SQL 需手动编写。
- 数据库移植性差。
3. #{} 和 ${} 的区别
特性 | #{} | ${} |
---|---|---|
处理方式 | 预编译(? 占位符) | 字符串替换 |
安全性 | 防 SQL 注入 | 有 SQL 注入风险 |
适用场景 | 参数值传递 | 动态表名、列名 |
4. 属性名和字段名不一致
- 别名:
SELECT user_name AS userName FROM user;
- ResultMap:
<resultMap id="userMap" type="User"> <result property="userName" column="user_name"/> </resultMap>
5. 分页实现
- 物理分页:SQL 的
LIMIT
/OFFSET
。 - 分页插件(PageHelper):拦截 SQL,自动添加分页语句。
6. 结果集封装
- 方式:
- 通过
ResultMap
映射字段和属性。 - 自动映射(属性名与字段名一致)。
- 通过
- 关联查询:
<association>
(一对一)、<collection>
(一对多)。
7. 批量插入
<insert id="batchInsert">
INSERT INTO user (name) VALUES
<foreach item="item" collection="list" separator=",">
(#{item.name})
</foreach>
</insert>
8. XML 映射文件标签
除基本 CRUD 标签外,还包括:
<resultMap>
:结果映射。<sql>
+<include>
:SQL 片段复用。<if>
、<choose>
:动态 SQL。<foreach>
:循环遍历。
9. 延迟加载及原理
- 延迟加载:需要时才加载关联对象(如查询订单时才加载用户信息)。
- 原理:通过动态代理生成关联对象的占位符,调用时触发查询。
10. 缓存机制
- 一级缓存:
作用域:SqlSession
级别(默认开启)。
失效场景:执行更新操作、手动清空缓存。 - 二级缓存:
作用域:Mapper
级别(需手动开启)。
失效场景:执行更新操作。
11. JDBC 编程步骤
- 注册驱动。
- 获取连接。
- 创建
Statement
。 - 执行 SQL。
- 处理
ResultSet
。 - 关闭资源。
12. MyBatis 中的设计模式
- 建造者模式:
SqlSessionFactoryBuilder
。 - 工厂模式:
SqlSessionFactory
。 - 代理模式:
Mapper
接口代理。 - 模板方法:
Executor
执行 SQL。
13. Mapper 接口无实现类调用原理
- 动态代理:运行时生成
MapperProxy
代理对象。 - 方法调用:代理对象拦截方法,根据方法名匹配 XML 中的 SQL。
14. 一二级缓存使用场景
- 一级缓存:同一
SqlSession
内多次相同查询。 - 二级缓存:跨
SqlSession
共享缓存数据(需注意数据一致性)。