MapperRegistry 的核心作用是 管理和维护已注册的 Mapper 接口。 可以将 MapperRegistry 理解为 MyBatis 中 Mapper 接口的注册中心 或 Mapper 接口的仓库。
MapperRegistry 的核心作用概括:
MapperRegistry 的主要作用是 跟踪和管理所有已注册的 Mapper 接口,并提供根据 Mapper 接口获取 Mapper 代理对象的能力。 它确保 MyBatis 能够正确地将 Mapper 接口与对应的 SQL 映射配置关联起来,并在运行时为 Mapper 接口创建代理对象,使得开发者可以通过调用 Mapper 接口方法来执行 SQL 操作。
更详细的解释和作用分解:
-
注册 Mapper 接口:
MapperRegistry负责 注册 所有需要被 MyBatis 管理的 Mapper 接口。 Mapper 接口的注册通常发生在 MyBatis 初始化阶段,在XMLConfigBuilder解析<mappers>元素时完成。 Mapper 接口可以通过以下几种方式注册到MapperRegistry中:-
通过
<mapper class="...">元素指定 Mapper 接口类:<mappers> <mapper class="com.example.mapper.UserMapper"/> </mappers>XMLConfigBuilder在解析到<mapper class="...">元素时,会读取class属性指定的 Mapper 接口类,并将其注册到MapperRegistry中。 -
通过
<package name="...">元素指定 Mapper 接口所在的包:<mappers> <package name="com.example.mapper"/> </mappers>XMLConfigBuilder在解析到<package name="...">元素时,会扫描name属性指定的包下的所有接口,并将这些接口作为 Mapper 接口注册到MapperRegistry中。 -
通过 Java 代码配置 (使用
Configuration对象):Configuration configuration = new Configuration(); configuration.addMapper(UserMapper.class); // 注册单个 Mapper 接口 configuration.addMappers("com.example.mapper"); // 注册包下所有 Mapper 接口可以使用
Configuration对象的addMapper(Class<T> type)和addMappers(String packageName)方法,通过 Java 代码显式地注册 Mapper 接口。 这些方法内部最终也会将 Mapper 接口注册到MapperRegistry中。
-
-
存储 Mapper 接口信息:
MapperRegistry内部使用Map<Class<?>, MapperProxyFactory<?>>数据结构来存储已注册的 Mapper 接口信息。- Key (
Class<?>): Mapper 接口的Class对象。 例如UserMapper.class。 - Value (
MapperProxyFactory<?>):MapperProxyFactory对象。MapperProxyFactory是一个工厂类,负责为 Mapper 接口 创建代理对象。 每个 Mapper 接口在MapperRegistry中都对应一个MapperProxyFactory实例。
MapperRegistry使用Map存储 Mapper 接口,使得可以 根据 Mapper 接口的Class对象快速查找和获取对应的MapperProxyFactory。 - Key (
-
获取 Mapper 接口代理对象:
MapperRegistry提供了getMapper(Class<T> type, SqlSession sqlSession)方法,用于 根据 Mapper 接口类型 (Class<T> type) 和SqlSession实例,获取 Mapper 接口的代理对象。SqlSession sqlSession = ...; // 获取 SqlSession 实例 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 通过 SqlSession 获取 UserMapper 接口的代理对象SqlSession.getMapper(Class<T> type)方法内部会 委托给MapperRegistry的getMapper()方法 来获取 Mapper 代理对象。MapperRegistry.getMapper()方法的执行流程如下:- 根据 Mapper 接口类型 (
Class<T> type),从内部的Map中查找对应的MapperProxyFactory。 - 如果找不到
MapperProxyFactory,表示该 Mapper 接口没有被注册,抛出BindingException异常。 - 如果找到了
MapperProxyFactory,调用MapperProxyFactory.newInstance(SqlSession sqlSession)方法,创建 Mapper 接口的代理对象。 - 返回创建的 Mapper 代理对象。
MapperProxyFactory负责创建 Mapper 接口的代理对象。 MyBatis 使用 JDK 动态代理或 CGLIB 动态代理 (取决于配置和环境) 来生成 Mapper 接口的代理对象。 代理对象会 拦截对 Mapper 接口方法的调用,并将方法调用委托给SqlSession的相应方法 (例如selectList,selectOne,insert,update,delete等) 来执行 SQL 操作。 - 根据 Mapper 接口类型 (
-
管理 Mapper 接口和 SQL 映射的关联:
MapperRegistry虽然本身不直接存储 SQL 映射配置 (MappedStatement,ResultMap等信息存储在Configuration对象中),但它 通过MapperProxyFactory间接地管理 Mapper 接口和 SQL 映射之间的关联关系。MapperProxyFactory在创建 Mapper 代理对象时,会持有SqlSession实例。- Mapper 代理对象在拦截 Mapper 接口方法调用时,会通过
SqlSession实例,根据 Mapper 接口方法名和 Mapper 接口命名空间,查找对应的MappedStatement对象 (SQL 映射)。 查找过程会委托给Configuration对象的getMappedStatement()方法。 - 找到
MappedStatement后,SqlSession会使用Executor执行MappedStatement中定义的 SQL 语句,并进行参数绑定和结果映射。
通过
MapperRegistry和MapperProxyFactory的协同工作,MyBatis 实现了 Mapper 接口和 SQL 映射的动态绑定,使得开发者可以通过面向接口的方式进行数据库操作,而无需手动编写 SQL 执行代码。
总结 MapperRegistry 的作用:
- 注册 Mapper 接口: 负责注册 MyBatis 应用中需要管理的 Mapper 接口。
- 存储 Mapper 接口信息: 使用
Map存储 Mapper 接口和对应的MapperProxyFactory。 - 获取 Mapper 代理对象: 提供
getMapper()方法,根据 Mapper 接口类型和SqlSession实例,获取 Mapper 接口的代理对象。 - 管理 Mapper 接口和 SQL 映射的关联 (间接): 通过
MapperProxyFactory,间接管理 Mapper 接口和 SQL 映射之间的关联关系,实现动态绑定。 - 为 MyBatis 的面向接口编程提供基础:
MapperRegistry是 MyBatis 面向接口编程的核心组件,使得开发者可以通过调用 Mapper 接口方法来执行数据库操作。
简单比喻:
你可以将 MapperRegistry 比喻成一个 Mapper 接口的注册中心 或 人才中介:
- 注册中心/人才中介 (
MapperRegistry): 负责登记和管理所有注册的 Mapper 接口 (人才)。 - Mapper 接口 (
人才): 代表了数据库操作的能力接口。 getMapper()方法 (获取人才): 根据 Mapper 接口类型 (人才类型),从注册中心获取对应的 Mapper 代理对象 (人才代理)。MapperProxyFactory(人才代理工厂): 负责创建 Mapper 接口的代理对象 (人才代理)。 代理对象会负责实际的数据库操作 (执行工作)。
MapperRegistry 就像一个人才中介,它管理着所有注册的 Mapper 接口 (人才),并能够根据需要,为开发者提供 Mapper 接口的代理对象 (人才代理),让开发者可以通过操作代理对象来间接执行数据库操作 (管理人才来完成工作)。

2062

被折叠的 条评论
为什么被折叠?



