原理--JDK动态代理产生mapper动态代理对象

1.通过反射获取方法注解或者xml文件中的sql语句

2.获取数据库连接(jdbc)

3.解析sql语句

4.执行sql语句

4.获取动态代理对象(最终对象,可以直接调用方法)

自己实现简单的mybatis动态代理

获取jdbc连接
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBManager {

    public static Connection getConn() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
            String user = "root";
            String pass = "1234567890";
            return DriverManager.getConnection(url, user, pass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
获取Mapper的动态代理
import java.lang.reflect.Proxy;

public class MapperProxy {

    public static Object getMapper(Class clazz) {
        /**
         * 传入三个参数
         * classLoader 代理对象的类加载器对象
         * Class<?>[] interfaces 代理类实现的接口的数组(可能会代理多个接口)
         *InvocationHandler h 方法调用分派给的invocationHandler
         */
        return Proxy.newProxyInstance(MapperProxy.class.getClassLoader(),
                new Class[]{clazz}, new MyInvocationHandler());
    }
}
Mapper类
import com.example.mybatisdemo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;

public interface UserMapper {
    @Select("select * from user")
    List<User> queryAll();
}
实体类User
import lombok.Data;
@Data
public class User {
    private int id;
    private String username;
    private String name;
    private int age;
    private int balance;
}
自定义类实现InvocationHandler
package com.example.mybatisdemo.test;

import com.example.mybatisdemo.entity.User;
import org.apache.ibatis.annotations.Select;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class MyInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //获取sql语句
        Select annotation = method.getAnnotation(Select.class);
        String sql = annotation.value()[0];
        System.out.println(sql);
        //解析sql语句
        Connection conn = DBManager.getConn();
        PreparedStatement ps = conn.prepareStatement(sql);
        //执行sql语句 jdbc
        ResultSet rs = ps.executeQuery();
        List<User> users = new ArrayList<>();
        while (rs.next()) {
            User user = new User();
            user.setId(rs.getInt("id"));
            user.setUsername(rs.getString("username"));
            user.setName(rs.getString("name"));
            user.setAge(rs.getInt("age"));
            user.setBalance(rs.getInt("balance"));
            users.add(user);
        }

        conn.close();
        rs.close();
        return users;
    }
}
测试类
import com.example.mybatisdemo.dao.UserMapper;
import com.example.mybatisdemo.entity.User;

import java.util.List;

public class TestMain {

    public static void main(String [] arg) {
        UserMapper userMapper = (UserMapper) MapperProxy.getMapper(UserMapper.class);
        List<User> users = userMapper.queryAll();
        for (User user : users) {
            System.out.println(
                    user.getId() + " "
                    + user.getUsername() + " "
                    + user.getName() + " "
                    + user.getAge() + " "
                    + user.getBalance()
            );
        }
    }
}
SQL文件
/*
 Navicat Premium Data Transfer

 Source Server         : localhostMysql
 Source Server Type    : MySQL
 Source Server Version : 50726
 Source Host           : localhost:3306
 Source Schema         : test

 Target Server Type    : MySQL
 Target Server Version : 50726
 File Encoding         : 65001

 Date: 07/10/2019 20:01:36
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `username` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `age` int(11) NOT NULL,
  `balance` int(11) UNSIGNED ZEROFILL NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'accout1', 'zhangsan', 20, 00000000100);
INSERT INTO `user` VALUES (2, 'accout2', 'lisi', 28, 00000000180);
INSERT INTO `user` VALUES (3, 'accout3', 'wangwu', 32, 00000000250);
INSERT INTO `user` VALUES (4, 'accout4', 'saozhu', 18, 00000000200);
INSERT INTO `user` VALUES (5, 'accout5', 'zhangtao', 22, 00000000540);

SET FOREIGN_KEY_CHECKS = 1;

笔者也是初学,写博客分享,有错误的地方以及不足的地方欢迎大家指正哈!