MyBatis核心之接口调用

本文探讨MyBatis在不依赖接口实现类的情况下,如何通过动态代理调用接口方法。详细介绍了创建Mapper接口、定义InvocationHandler、创建Mapper工厂以及在实际测试中的应用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在平时开发中,我们一般使用mybatis是这样的:

创建一个接口(此处暂时忽略mybatis加载配置文件的过程):

@Mapper
public interface UserMapper {

	public void update(User user);
}

配置一个XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tongmin.mapper.UserMapper">

    <update id="update" parameterType="com.tongmin.entity.User" >
        update user
        <set >
            <if test="userName != null" >
                user_name = #{userName,jdbcType=VARCHAR},
            </if>
            <if test="passWord != null" >
                pass_word = #{passWord,jdbcType=VARCHAR},
            </if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>

</mapper>

接下来在业务中注册UserMapper,然后就直接调用方法update。

到这里,就有一个问题,接口是不能实例化的,那么我们是怎么直接调用接口的方法的呢?

在mybatis中使用了动态代理来解决这个问题,但是mybatis的动态代理又不一样,普通的动态代理是需要有接口实现类,而mybatis的动态代理是不需要接口实现类的。

此处模拟一个动态代理:

创建一个Mapper

public interface RoleMapper {

	public void getRole();
}

创建一个InvocationHandler:

public class ProxyInvocationHandler implements InvocationHandler{

	
	public ProxyInvocationHandler(){
		
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object object = null;
		
		//此处执行具体的业务逻辑,如根据方法名称加载sql语句,
                //根据方法名称加载参数,根据方法名称加载返回结果类型
                System.out.println("执行具体的业务逻辑");
        
		return object;
	}

}

创建一个Mapper工厂:

public class ProxyFactory<T> {

	private ProxyInvocationHandler handler;
	
	private Class<T> interfaceName;
	
	public ProxyFactory(ProxyInvocationHandler handler,Class<T> interfaceName) {
		this.handler = handler;
		this.interfaceName = interfaceName;
	}
	//创建具体的代理对象
	public T getInterface(){
		T clazz = (T) Proxy.newProxyInstance(interfaceName.getClassLoader(), new Class[]{interfaceName}, handler);
		return clazz;
	}
}

具体的测试类:

public class ProxyTest {

	public static void main(String[] args) {
		ProxyInvocationHandler handler = new ProxyInvocationHandler();
		ProxyFactory<RoleMapper> factory = new ProxyFactory<RoleMapper>(handler, RoleMapper.class);
		System.out.println(factory.getInterface().getRole());
	}
}

 

<think>好的,用户想了解MyBatis中Mapper接口的实现原理,特别是动态代理和SQL映射的部分。我需要结合之前提供的引用内容来整理回答。 首先,根据引用[2]和[3],Mapper接口没有实现类,MyBatis通过动态代理生成代理对象。这点是关键。用户可能疑惑为什么接口没实现却能调用方法,动态代理就是答案。需要解释动态代理的作用,比如拦截方法调用。 接下来,引用[1]提到MapperProxy类,这是核心类,负责处理代理逻辑。应该详细说明MapperProxy如何拦截方法调用,将其转化为对应的SQL操作。比如,当调用selectAll()方法时,MapperProxy会找到对应的SQL语句并执行。 然后,引用[4]中的示例接口和映射文件需要关联起来。说明MyBatis如何将接口方法与XML中的SQL语句绑定,可能是通过方法名和命名空间的匹配。需要提到接口的全限定名和XML的namespace必须一致,方法名对应SQL的id。 另外,要提到SqlSession的作用,比如SqlSession.getMapper()方法触发代理对象的创建,这里可能需要结合引用[3]中的源码分析部分。 还需要注意动态代理的“非常规”用法,这里指的是不同于常见的代理方式,MyBatis并没有提前编写实现类,而是在运行时动态生成。这部分可以引用引用[2]的内容。 最后,总结整个流程,从调用接口方法到代理对象处理,再到执行SQL,确保用户理解整个过程。同时,生成的相关问题需要覆盖动态代理机制、接口与XML的绑定、性能优化等可能延伸的方向。 检查是否有遗漏点,比如SQL映射的解析过程,或者配置文件的加载机制,但根据用户的问题,可能不需要太深入,保持回答在原理层面即可。</think>### MyBatis Mapper接口实现原理分步解析 #### 1. 动态代理机制 MyBatis通过JDK动态代理为Mapper接口生成代理对象(核心类为$MapperProxy$)。当调用接口方法时,$MapperProxy$会拦截方法调用,并根据方法名和参数解析对应的SQL语句[^2]。 ```java // 简化的代理调用逻辑 public class MapperProxy implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) { // 1. 解析方法对应的SQL命令 // 2. 执行数据库操作 // 3. 返回处理结果 } } ``` #### 2. SQL映射绑定 接口方法与XML映射文件的绑定通过以下方式实现: - **命名空间对应**:XML的`namespace`必须与Mapper接口全限定名一致 - **方法签名匹配**:接口方法名对应XML中SQL语句的`id` - **参数映射**:通过`@Param`注解或参数顺序绑定参数 例如引用[4]中的接口方法: ```xml <!-- XML映射文件 --> <mapper namespace="com.example.UserMapper"> <select id="selectAll" resultType="User"> SELECT * FROM users </select> </mapper> ``` #### 3. 执行流程 1. 通过`SqlSession.getMapper()`获取代理对象 2. 调用接口方法时触发$MapperProxy$的`invoke()`方法 3. 通过$MapperMethod$解析SQL类型(SELECT/UPDATE等) 4. 使用$SqlSession$执行具体数据库操作 5. 结果集通过$TypeHandler$进行类型转换 #### 4. 核心组件关系 $$ \begin{array}{ccc} \text{Mapper接口} & \xrightarrow{\text{动态代理}} & \text{MapperProxy} \\ & & \downarrow \\ \text{XML映射文件} & \xleftarrow{\text{元数据解析}} & \text{Configuration} \end{array} $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tong472687551

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值