MyBatis 中比如 UserMapper.java 是接口,为什么没有实现类还能调用?
1 个回答
首先你要快乐,其次都是其次。谭新宇### MyBatis 中 UserMapper 接口为什么没有实现类还能调用? 在 MyBatis 中,`UserMapper` 这样的接口没有显式的实现类,但仍然可以调用其方法。这是因为 MyBatis 使用了 **JDK 动态代理** 和 **MapperProxy** 来实现这一功能。 #### 原理解析 1. **JDK 动态代理** - MyBatis 使用 JDK 动态代理为 Mapper 接口生成代理对象。 - JDK 动态代理需要提供一个接口和一个调用处理器(InvocationHandler)。 - MyBatis 在运行时生成代理类,这个代理类实现了 Mapper 接口。 2. **MapperProxy** - `MapperProxy` 是 MyBatis 提供的调用处理器,实现了 `InvocationHandler` 接口。 - `MapperProxy` 的 `invoke` 方法负责拦截对 Mapper 接口方法的调用。 #### 具体实现步骤 1. **创建 SqlSession** - 首先,通过 `SqlSessionFactory` 创建一个 `SqlSession` 实例。 - **示例代码**: ```java SqlSession session = sqlSessionFactory.openSession(); ``` 2. **获取 Mapper 的代理对象** - 使用 `SqlSession.getMapper(UserMapper.class)` 方法获取 Mapper 接口的代理对象。 - **示例代码**: ```java UserMapper userMapper = session.getMapper(UserMapper.class); ``` 3. **调用代理对象的方法** - 调用代理对象的方法时,实际上是由 `MapperProxy` 的 `invoke` 方法拦截并处理。 - **示例代码**: ```java User user = userMapper.selectUserById(1); ``` #### MapperProxy 的工作机制 1. **拦截方法调用** - 当调用 `userMapper.selectUserById(1)` 时,代理对象会拦截这个调用。 - **示例代码**: ```java @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 拦截方法调用,处理逻辑 } ``` 2. **获取 Mapper 方法的相关信息** - `MapperProxy` 获取被调用方法的 `MappedStatement`,该对象包含了 SQL 语句、参数映射和结果映射等信息。 - **示例代码**: ```java final MapperMethod mapperMethod = cachedMapperMethod(method); ``` 3. **执行 SQL 语句** - `MapperProxy` 使用 `SqlSession` 执行相应的 SQL 语句。 - **示例代码**: ```java return mapperMethod.execute(sqlSession, args); ``` 4. **返回结果** - `MapperProxy` 处理 SQL 执行结果,并将结果返回给调用者。 - **示例代码**: ```java return sqlSession.selectOne(statement, parameter); ``` ### 总结 在 MyBatis 中,`UserMapper` 接口没有显式的实现类但仍能调用,是因为 MyBatis 使用了 **JDK 动态代理** 和 **MapperProxy**。其本质上是调用了 `MapperProxy` 的 `invoke` 方法来处理接口方法的调用。 1. **JDK 动态代理**:在运行时生成代理类,实现 Mapper 接口。 2. **MapperProxy**:作为调用处理器,拦截方法调用并执行相应的 SQL 语句。 通过这种方式,MyBatis 实现了对 Mapper 接口方法的动态代理,使得开发者可以直接使用接口进行数据库操作而不需要编写实现类。发布于 2024-07-23 13:14 •IP属地 云南举报评论收藏
公众号进入网站体验更佳

