• mybatis-config.xml里标签可以放置多个environment,这里可以切换test和develop数据源
  • databaseIdProvider提供多种数据库,在xml映射文件里选择databaseId即可使用对应的数据库
  • Oracle的自增是使用Sequence实现的,若要获取插入数据的主键,在xml映射里写上selectKey标签,select seq.nextval from dual;
  • 哪些地方不能使用占位符?比如分表时表名,orderby,desc
  • @Mapkey("id")指定返回类型为map时,将id作为key

1. mybatis参数绑定的过程

我们写一个UserMapper接口,Mybatis会为改接口创建一个MapperProxy对象。

1.1 MapperRegistry

在继续之前,先来了解一下MapperRegistry。

  1. MapperRegistry是mapper的注册类,提供了注册一个包下面的所有Mapper接口。内部维护了一个 private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();map以mapper接口类为key,value是接口类对应的代理工厂。

    void addMapper(Class<T> type)方法简单的将type放进knownMappers里面。不过,这里面还有
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();

这样一个解析操作,暂不做分析。

2. <T> T getMapper(Class<T> type, SqlSession sqlSession)该方法是本类最重要的一个方法了,获取Mapper接口的代理对象也正是从该方法获取的。

该方法实现就是,knownMappers.get(type)得到代理对象工厂mapperProxyFactory,返回的是mapperProxyFactory.newInstance(sqlSession)

进入该方法发现过程也比较简单,构造了一个MapperProxy对象

   public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}

再进去看

  protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

发现这就是标准的JDK面向接口的动态代理啊。要问对应的InvocationHandler在哪里?mapperProxy就是啦。

至此,Mybatis如何获取Mapper接口的代理对象已经解决。

再梳理一下整个流程:

sqlsession.getMapper->configuration.getMapper->mapperRegistry.getMapper->获取Mapper代理对象

1.2

创建好MapperProxy对象之后,调用Mapper.xx方法时就会走MapperProxy的invoke方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {//如果方法是在Object里面的,放行
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);//缓存method方法
return mapperMethod.execute(sqlSession, args); // 执行
}

发现关键点在于mapperMethod.execute(sqlSession, args)方法

Mybatis获取代理对象的更多相关文章

  1. 在spring中获取代理对象代理的目标对象工具类

    昨天晚上一哥们需要获取代理对象的目标对象,查找了文档发现没有相应的工具类,因此自己写了一个分享给大家.能获取JDK动态代理/CGLIB代理对象代理的目标对象. 问题描述:: 我现在遇到个棘手的问题,要 ...

  2. mybatis源码分析(四)---------------代理对象的生成

    在mybatis两种开发方式这边文章中,我们提到了Mapper动态代理开发这种方式,现在抛出一个问题:通过sqlSession.getMapper(XXXMapper.class)来获取代理对象的过程 ...

  3. 6、Spring+Struts2+MyBatis(mybatis有代理)整合增删改查

    1.创建如下的oracle脚本 create table userinfo (id ), name ), password telephone ), isadmin )); --4.2 用户表序列 c ...

  4. Mybatis 接口代理的实现(BeanDefinitionRegistryPostProcessor+FactoryBean)

    相信在开发中,尤其是mybatis 配置操作中,我们只需要提供一个mapper 接口,然后注入到service 中,就可以进行调用. 按我们的一般逻辑来说,我们并没有进行接口的实现,应该会报空指针异常 ...

  5. Mybatis动态代理实现函数调用

    如果我们要使用MyBatis进行数据库操作的话,大致要做两件事情: 1. 定义DAO接口 在DAO接口中定义需要进行的数据库操作. 2. 创建映射文件 当有了DAO接口后,还需要为该接口创建映射文件. ...

  6. dubbo源码分析三:consumer注册及生成代理对象

    本章我们将分析一下consumer向注册中心注册,并获取服务端相应的信息,根据这些信息生产代理对象的过程和源码. 1.类图 上图展示了部分消费者注册及生成代理对象过程中需要使用到的类和接口,其中: s ...

  7. Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程

    spring-aop-4.3.7.RELEASE  在<Spring AOP高级——源码实现(1)动态代理技术>中介绍了两种动态代理技术,当然在Spring AOP中代理对象的生成也是运用 ...

  8. Springboot源码分析之代理对象内嵌调用

    摘要: 关于这个话题可能最多的是@Async和@Transactional一起混用,我先解释一下什么是代理对象内嵌调用,指的是一个代理方法调用了同类的另一个代理方法.首先在这儿我要声明事务直接的嵌套调 ...

  9. 二、openfeign生成并调用客户端动态代理对象

    所有文章 https://www.cnblogs.com/lay2017/p/11908715.html 正文 上一篇文章中,我们了解到了@FeignClient注解的接口被扫描到以后,会生成一个Fe ...

随机推荐

  1. python方法和函数集锦

    方法的使用: 变量.方法名(参数) 函数的使用: 函数名(参数) 字符串 1.删除空白 rstrip(): 返回去掉尾部的空格后的字符串.(不改变原字符串) lstrip(): 去掉首部空格 stri ...

  2. ajax 的登录认证

    在models中 先创建一个表 from django.db import models # Create your models here. class UserInfo(models.Model) ...

  3. 学Redis这篇就够了

    Redis 简介 Redis 优势 Redis 数据类型 string hash list set Zset 小总结 基本命令 发布订阅 简介 实例 发布订阅常用命令 事务 实例 Redis 事务命令 ...

  4. 安卓学习资料推荐《深入理解Android:卷2》下载

    下载地址:百度云下载地址 编辑推荐 <深入理解Android:卷2>编辑推荐:经典畅销书<深入理解Android:卷I>姊妹篇,51CTO移动开发频道和开源中国社区一致鼎力推荐 ...

  5. 20131228-sql命令

    开始 --cmd net start mssqlservernetnet stop mssqlserver

  6. [原创]MYSQL周期备份shell脚本

    这个脚本是实现阿里云mysql数据库全量周期备份的shell脚本,实现备份数据按一周星期几分开存放.一下是脚本内容: #!/bin/bash echo `date`echo "backup ...

  7. [Spring-Cloud-Alibaba] Sentinel 整合RestTemplate & Feign

    Sentinel API Github : WIKI Sphu (指明要保护的资源名称) Tracer (指明调用来源,异常统计接口) ContextUtil(标示进入调用链入口) 流控规则(针对来源 ...

  8. 一个测试文件与源文件位于不同模块时Jacoco覆盖率配置的例子

    问题描述: 我们有个多模块项目,由于种种原因(更常见的可能是需要集成测试)测试文件和源文件不在一个模块,Jacoco的覆盖率无法正确显示,查询了一些资料,发现中文的例子比较少,就把我自己的Demo贴一 ...

  9. MapReduce之提交job源码分析 FileInputFormat源码解析

    MapReduce之提交job源码分析 job 提交流程源码详解 //runner 类中提交job waitForCompletion() submit(); // 1 建立连接 connect(); ...

  10. [PTA] 数据结构与算法题目集 6-4 链式表的按序号查找 & 6-5 链式表操作集 & 6-6 带头结点的链式表操作集

    带不带头结点的差别就是,在插入和删除操作中,不带头结点的链表需要考虑两种情况:1.插入(删除)在头结点.2.在其他位置. 6.4 //L是给定单链表,函数FindKth要返回链式表的第K个元素.如果该 ...