原理分析Java Mybatis中的Mapper

准备

1.pom文件

 
        
        
            org.mybatis
            mybatis
            3.4.5
        
        
        
            mysql
            mysql-connector-java
            5.1.6
            runtime
        
        
        
            junit
            junit
            4.12
            test
        
        
        
            log4j
            log4j
            1.2.12
        

        
            org.projectlombok
            lombok
            1.18.2
            provided
        
    

2.user类-数据库

原理分析Java Mybatis中的Mapper_第1张图片

3.实体类

@Getter
@Setter
@ToString
@NoArgsConstructor
public class user {
    private int id;
    private String username;
    private String password;
}

4.dao 层

public interface userDao {
    List findAll();
}

5.Mapper 文件




    

核心配置文件




    
    
    
    
        
    
    
    
        
            
            
                
                
                
                
            
        
    

    
    
        
    


核心代码

import dao.userDao;
import mode.user;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class TestMapper {
    public static void main(String[] args) throws IOException {
        //加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //获得sqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new
                SqlSessionFactoryBuilder().build(resourceAsStream);
        //获得sqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行sql语句
        userDao mapper = sqlSession.getMapper(userDao.class);
        List userList = mapper.findAll();
        //打印结果
        System.out.println(userList);
        //释放资源
        sqlSession.close();
    }
}

源码分析

1.断点

原理分析Java Mybatis中的Mapper_第2张图片

2.查看源码

DefaultSqlSession:

在这里插入图片描述

Configuration:

原理分析Java Mybatis中的Mapper_第3张图片

这是Configuration 类。我们主要看getMapper()方法

原理分析Java Mybatis中的Mapper_第4张图片

MapperRegistry:

原理分析Java Mybatis中的Mapper_第5张图片

关键代码:mapperProxyFactory.newInstance(sqlSession);

MapperProxyFactory:

原理分析Java Mybatis中的Mapper_第6张图片

返回的是MapperProxy 对象

MapperProxy:

源码:

// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.apache.ibatis.binding;
import java.io.Serializable;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import org.apache.ibatis.lang.UsesJava7;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.session.SqlSession;
public class MapperProxy implements InvocationHandler, Serializable {
    private static final long serialVersionUID = -6424540398559729838L;
    private final SqlSession sqlSession;
    private final Class mapperInterface;
    private final Map methodCache;
    public MapperProxy(SqlSession sqlSession, Class mapperInterface, Map methodCache) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
        this.methodCache = methodCache;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(this, args);
            }
            if (this.isDefaultMethod(method)) {
                return this.invokeDefaultMethod(proxy, method, args);
            }
        } catch (Throwable var5) {
            throw ExceptionUtil.unwrapThrowable(var5);
        }
        MapperMethod mapperMethod = this.cachedMapperMethod(method);
        return mapperMethod.execute(this.sqlSession, args);
    }
    private MapperMethod cachedMapperMethod(Method method) {
        MapperMethod mapperMethod = (MapperMethod)this.methodCache.get(method);
        if (mapperMethod == null) {
            mapperMethod = new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration());
            this.methodCache.put(method, mapperMethod);
        }
        return mapperMethod;
    }
    @UsesJava7
    private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable {
        Constructor constructor = Lookup.class.getDeclaredConstructor(Class.class, Integer.TYPE);
        if (!constructor.isAccessible()) {
            constructor.setAccessible(true);
        }
        Class declaringClass = method.getDeclaringClass();
        return ((Lookup)constructor.newInstance(declaringClass, 15)).unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args);
    }
    private boolean isDefaultMethod(Method method) {
        return (method.getModifiers() & 1033) == 1 && method.getDeclaringClass().isInterface();
    }
}

原理分析Java Mybatis中的Mapper_第7张图片

在invoke方法中可以看到,如果我们调用的是Object中的方法,不做任何处理,直接调用,否则执行:

mapperMethod.execute(this.sqlSession, args);

MapperMethod:

原理分析Java Mybatis中的Mapper_第8张图片

在MapperMethod 中对SQL语句进行分类反射

总结

  • MapperProxyFactory中,使用JDK的动态代理生成Mapper接口的代理代理类
  • 由动态处理器MapperProxy中调用MapperMethod中的方法处理执行SQL
  • 最后,在MapperMethod中根据执行的方法返回值决定调用SqlSession中的对应方法执行SQL

 本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

你可能感兴趣的:(原理分析Java Mybatis中的Mapper)