我们可以在官方文档中知道,Mybatis可以使用动态代理来进行mapper xml文件与接口的连接。
不过我们发现当我们在接口中出现重载的方法的时候,我们在相应的mapper文件中也会定义两个id一样的节点。
当我们启动项目的时候,就会发现项目运行会出现错误,导致项目无法运行。
那么为什么在mapper中定义两个或者多个重名方法节点会导致错误呢。这肯定和id的唯一性有关。
下面我们通过源码来尝试解释一下这个流程。
mybatis动态代理主要是使用SqlSessionFactoryBean(org.mybatis.spring.SqlSessionFactoryBean)类,我们会为这类注入我们的配置文件mapperLocations。
项目启动的时候会实例化这类,同时会调用buildSqlSessionFactory()来创建与数据库的连接工厂来维护我们的项目中用到的部分bean。
这个时候,mybatis会根据我们配置的xml(这里不是指单个mapper,而是根据我们的配置路径获取mapper集合(也可能是单个mapper),也就是mappers,多个路径会被加载多次,每每个路径下的如果有N个文件就会产生N个Resource)来分析我们配置的mappers。
因为对每一个mapper,我们会分析里面的节点,因为mapper是xml格式的嘛!所以还需要对节点进行迭代逐个分析
Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator();
while (iter.hasNext()) {
try {
iter.next().parseStatementNode();
iter.remove();
} catch (IncompleteElementException e) {
// Statement is still missing a resource...
}
}
资源会被加载到xmlMapperBuilder对象中,同时xmlMapperBuilder的parse()方法来分析我们的配置,分析的顺序是先分析ResultMap,再分析ChacheRef,最后分析Statements。
现在因为我们项目中,有重载的方法,或者同一个DAO层下面会有两个以及多个相同名称的方法,虽然他们参数类型和参数个数不一样。
所以我们关于ResultMap结果集和ChacheRef缓存不是本次讨论重点,我们着重看Statements语句声明。
在parsePendingStatements()中,我们会对Statements进行分析,因为mapper会包含多个Statement会对每一个Statement进行处理。
在parseStatementNode()中,我们会得到每一个声明语句的属性以及属性值,其中本次讨论的核心是id,所以我们只关心属性id。
我们会将每个Statement的属性值添加到builderAssistant的MappedStatement对象中,这里面存放的就是一条条的声明语句。
在我们真正将声明语句添加到MappedStatement中,我们需要通过statementBuilder的build()来构建MappedStatement对象。
在此之前,我们都不会去检查MappedStatement是否有重复的内容,以及如何去检查,都是在构建好MappedStatement对象之后处理的。
当我们构建好MappedStatement对象之后,我们才开始真正将MappedStatement对象通过put操作添加到configuration(全局配置对象)的mappedStatements(这是一个map)中。而Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>(...);
并不是我们常见的HashMap,我们在深入看一下发现class StrictMap<V> extends HashMap<String, V> ,原来StrictMap继承了HashMap。
那我们使用的put是不是也是一样的呢?
结果是否定的!!!
public V put(String key, V value) {
if (containsKey(key)) //这一句是核心
throw new IllegalArgumentException(name + " already contains value for " + key);
//此处省略...
}
return super.put(key, value);
}
很明显,我们在put之前,做了一些检查,如果有重复的也就是id相同的声明语句,那么就会报错!
这就是为什么Mybatis动态代理中无法实现方法重载的原因。