待解决
//TODO 面试题
为啥mybatis的mapper只有接口没有实现类,但它却能工作??(ai参考,待深究源码)
1. 动态代理生成代理对象
MyBatis 使用 JDK 动态代理 为每个 Mapper 接口生成代理对象: • 核心类 :MapperProxy
(实现 InvocationHandler
接口)和 MapperProxyFactory
(代理工厂)。 • 代理对象创建流程:
-
当调用
SqlSession.getMapper(UserMapper.class)
时,MyBatis 会通过MapperProxyFactory
创建代理对象。 -
MapperProxy
作为代理逻辑处理器,拦截所有接口方法的调用。 -
代理对象通过
Proxy.newProxyInstance
动态生成,无需手动编写实现类。
2. 方法调用与 SQL 执行的映射
代理对象拦截方法调用后,通过以下步骤执行 SQL: • 步骤 1:解析方法签名 根据接口全限定名(如 com.example.UserMapper
)和方法名(如 getUserById
),生成唯一的 方法 ID (例如 com.example.UserMapper.getUserById
)。
• 步骤 2:绑定 SQL 语句 MyBatis 启动时会加载 XML 文件,将 <mapper>
标签的 namespace
与接口全限定名匹配,并通过方法 ID 找到对应的 SQL 语句。
• 步骤 3:执行 SQL 并返回结果 代理对象通过 SqlSession
调用底层方法(如 selectOne
、selectList
),执行 SQL 并将结果映射为 Java 对象。
3. 关键设计优势
• 解耦接口与实现 开发者只需定义接口和 SQL 映射,MyBatis 自动生成代理对象,避免手动编写模板代码。
• 灵活性与可维护性 SQL 与 Java 代码分离,修改 SQL 无需重新编译代码,同时支持动态 SQL 和复杂映射。
• 性能优化 代理对象通过缓存 MappedStatement
(包含 SQL、参数、结果映射等信息)提升执行效率。
4. 话术
-
MapperProxy
的invoke
方法 代理对象调用方法时,会进入MapperProxy.invoke
,通过MapperMethod
封装 SQL 执行逻辑。(封装?还是映射?) -
Configuration
类的核心作用 在 MyBatis 启动时,Configuration
类会加载所有 Mapper 接口和 XML 文件,建立接口方法与 SQL 的映射关系。