Mybatis核心原理(对象代理):简单模拟注解形式工作流程

一、完整代码

Mybatis核心原理:对象代理
我们只需要按照原生Java的使用方式进行数据库操作即可,Mybatis内部对原生对象进行加强处理得到一个对应的代理对象,我们通过当前对象方法调用进行数据库操作时,实质是Mybatis内部生成的代理对象内部的统一方法在进行工作。
举例,我们通过UserMapper接口声明一个userMapper对象,Mybatis内部验证发现userMapper对象被mapper注解修饰,因此对该userMapper对象进行加强处理得到一个对应的代理对象,也就是我们真正拿到的userMapper对象是一个代理对象。后续在通过userMapper调用selectAll方法时,Mybatis内部对其进行拦截,统一执行内部的invoke方法,真正实现JDBC操作的过程是通过invoke方法实现的。

1.实体类User

@Data
public class User {
    
    
    private Integer uid;
    private String username;
    private String password;
    private String avatarUrl;

    public User(){
    
    
        System.out.println("User()无参构造");
    }
}

2.Mapper接口UserMapper

public interface UserMapper {
    
    
    @Select("select * from users")
    List<User> selectAll();
}

此处使用的Select注解是我们自定义的注解,其中的value用于保存该注解内部的SQL语句:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
    
    
    String value();  // 存储对应的SQL语句
}

3.代理对象

原生Java对象一旦生成代理对象,则通过该对象调用原生方法时,实质会被拦截执行invoke方法

public class ProxyObject  implements InvocationHandler {
    
      //InvocationHandler:调用管理,所有调用都会进入invoke方法
    private DataSource dataSource;  // 数据源

    {
    
    
        MysqlDataSource mysqlDataSource=new MysqlDataSource();
        // 数据库参数设置
        mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/sys25?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai");
        mysqlDataSource.setUser("root");
        mysqlDataSource.setPassword("123456");
        dataSource=mysqlDataSource;
    }

    @Override
    // method:指的是原生User对象所调用的方法
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
    
    
        // 获取注解信息
        Select annotation = method.getAnnotation(Select.class);
        String sql = annotation.value();  // 对应的sql语句

        // 真正执行JDBC查询操作
        List<User> userList=new ArrayList<>();
        try(Connection connection=dataSource.getConnection()){
    
    
            try (PreparedStatement statement=connection.prepareStatement(sql)){
    
    
                try (ResultSet resultset=statement.executeQuery()){
    
    
                    while (resultset.next()){
    
    
                        User user=new User();
                        int uid = resultset.getInt("uid");
                        String username=resultset.getString("username");
                        String password=resultset.getString("password");
                        String avatar_url=resultset.getString("avatar_url");

                        user.setUid(uid);
                        user.setUsername(username);
                        user.setPassword(password);
                        user.setAvatarUrl(avatar_url);
                        userList.add(user);
                    }
                }
            }

        }
        return userList;
    }
}

4.程序入口

public class Main {
    
    
    public static void main(String[] args) {
    
    
        UserMapper userMapper=getByString();  // 其实获取的是一个代理对象,由Mybatis内部进行加强处理得到
        List<User> userList = userMapper.selectAll();
        for (User user:userList){
    
    
            System.out.println(user);
        }

    }

    public static UserMapper getByString(){
    
    
        return (UserMapper)Proxy.newProxyInstance(
                Main.class.getClassLoader(),
                new Class[]{
    
    UserMapper.class},
                new ProxyObject()
        );
    }
}

查询结果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43665602/article/details/128892654
今日推荐