mybatis实现源码简析

一、概述

用spring+mybatis搭建项目的时候,刚开始就有个困惑,Mapper只有接口,没有实现,那么怎么样实现底层的sql查询呢,后来网上查资料,加上有了设计模式的相关知识后,才知道用的是java的动态代理技术生成了代理类MapperProxy,mybatis的运行逻辑上分为二部分,一部分根据接口生成接口动态代理类,二是执行接口的方法时,实际上执行的是接口的动态代理的invoke方法,执行参数绑定、操作、返回参数的解析;

二、源码解析:

我们都知道mybatis的执行离不开sqlsession,那么代理类又是如何多SqlSession进行封装的呢?带着这些疑问,让我们通过分析源代码的方式来解释这些问题。

sqlSession的调用:

//获取session  
        SqlSession session = sqlSessionFactory.openSession();  
        //获取mapper接口的代理对象  
        UserMapper userMapper = session.getMapper(UserMapper.class);  
        //调用代理对象方法  
        User user = userMapper.findUserById(27);  
        System.out.println(user);  
        //关闭session  
        session.close();  
        System.out.println("---------执行完毕-----------");  
我们主要看下面这个方法
UserMapper userMapper = session.getMapper(UserMapper.class);  

@Override
public <T> T getMapper(Class<T> type) {
  return configuration.<T>getMapper(type, this);
}
这个是上面getMapper的实现,跟进代码里面发现了MapperRegistry类,

mybatis封装mapper接口的主要有四个类,位于org.apache.ibatis.binding包下面,MapperRegistry是注册代理接口与获取代理类实例的工具类,如下:

/**
 *    Copyright 2009-2015 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.binding;

import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder;
import org.apache.ibatis.io.ResolverUtil;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author Clinton Begin
 * @author Eduardo Macarron
 * @author Lasse Voss
 */
public class MapperRegistry {

  //全局配置文件对象
  private final Configuration config;
  //一个Map,key是Mapper类型的Class类型对象,value是创建Mapper代理对象的工厂
 private final Map, MapperProxyFactory> knownMappers = new HashMap, MapperProxyFactory>();

  public MapperRegistry(Configuration config) {
    this.config = config;
  }

 //根据Mapper的Class类型对象和SqlSession对象得到Mapper的代理对象
  @SuppressWarnings("unchecked")
 public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  //根据type获取mapper代理对象工厂的实例,如果没有获取到,抛出异常
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
     //创建一个当前接口的代理对象传到sqlSession
     return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
  
  public <T> boolean hasMapper(Class<T> type) {
    return knownMappers.containsKey(type);
  }

  public <T> void addMapper(Class<T

你可能感兴趣的:(mybatis,mybatis)