Mybatis实现Mapper接口的简单案例

 用了很久mybatis,一直猜想mybatis是使用动态代理的方式实现mapper接口的,通过实践探索之后,果然如此,但是还是遇到了不少问题,在此粘出来供初学者参考。
首先我将案例代码粘出来,这段代码简单实现了从service层开始调用mapper接口的过程。

package com.star.ott.common.office;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestClass {

    public static void main(String[] args) {
        new UserService().updateUserByUserName();
        new UserService().findUser("");
    }

}

/**
 * 我们需要操作的user实体
 */
class User {
    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

/**
 * 这里是我们的mapper接口
 */
interface UserMapper {
    User findUserByUserName(String userName);

    void updateUserByUserName(User user);
}

/**
 * 此处是service层的业务类
 */
class UserService {
    //在实际开发中,此处的UserMapper是通过注解加载进来的,而其真正的
    //实现就类似于下面的实现方式,通过动态带来的方式创建实例
    UserMapper userMapper = (UserMapper) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{UserMapper.class}, new MybatisProxy());

    public User findUser(String userName) {
        return userMapper.findUserByUserName(userName);
    }

    public void updateUserByUserName() {
        userMapper.updateUserByUserName(new User());
    }
}

/**
 * 这里就是具体的代理类,在代理类中,通过数据库驱动与数据库获取
 * 连接,然后读取相关mapper.xml执行sql,最后获得操作结果,具体
 * 连接数据库,读取mapper.xml文件的方式就不再累赘
 */
class MybatisProxy implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("遍历参数" + method.getParameters()[0]);
        System.out.println("通过method的名字去mapper.xml文件中找到sql: " + method.getName());
        System.out.println("执行数据库操作,若果有异常等,直接在此处抛出,没有则拿到返回值");
        if(method.getReturnType().toString().equals("void")){
            System.out.println("无返回值的情况");
            return method.getGenericReturnType();
        }else {
            Object result = method.getReturnType().getDeclaredConstructor().newInstance();
            System.out.println("将得到的返回值赋值给result,然后返回" + method.getReturnType());
            return result;
        }
    }
}



需要注意的是,通过Proxy.newProxyInstance方式生成代理对象时,一般除了需要接口类的类类型之外,还需要实现类的实例作为代理类的参数,这样,我们就可以在代理对象中,也就是MybatisProxy中直接执行实现类实例的方法,然后返回。但是我们此处代理对象的特殊之处,就是代理了接口,实现逻辑完全写在代理类中,所以遇到没有返回值的方法时,需要做逻辑判断,返回一个method.getGenericReturnType(),否则这里会报错。
好了,这就是mybatis通过动态代理的方式实现mapper接口的大致方式,可以参考一下。

你可能感兴趣的:(学习笔记)