这篇主要看下mybatis的Mapper,Mapper能够说是mybatis的入口。这里仅讨论注解的方式。
回顾下第一篇中mybatis是如何使用的。java
sqlSession = SqlSessionFactoryUtil.getSqlSession(); productMapper = sqlSession.getMapper(ProductMapper.class); Product product = productMapper.detail(1);
能够看到获取Session后(第二篇讲到了,本质就是获取到一个数据库链接),获取productMapper,ProductMapper是咱们定义的一个接口,detail是咱们定义的一个抽象方法。 接口并无实现方法,所以能够猜测到mybatis帮咱们生成了一个实现了ProductMapper接口的类。sql
那能够试想下,让咱们本身实现这个类,是怎样的流程呢?
首先,getMapper有个入参是ProductMapper.class。也就是咱们有ProductMapper这个接口,接口上每一个方法中的注解上都定义了该如何执行sql。经过反射可以拿到这些sql信息。生成类则可使用动态代理,由于ProductMapper是接口,咱们能够用jdk动态代理。数据库
mybatis生成productMapper是分两步的,第一步是在初始化的时候addMapper,第二步则是在使用的时候getMapper。为何要这样作呢,由于解析注解、生成工厂类等都是重复的工做。能够在初始化前计算好。使用的时候拿来用就好了。mybatis
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } }
getMapper的流程比较简单,就是经过Mapper在knownMappers(addMapper中会讲)中取到对应的Mapper代理工厂。而后经过工厂构建Mapper代理。app
能够看到最终一共生成了三份重要数据,类型分别为Mapper代理工厂类,ResultMap,MappedStatement类。都保存在了Map结构中。
knowMappers保存在了configuration.mapperRegistry中。键是Mapper.class,值是对应的Mapper代理工厂。
resultMaps保存在了configuration中。键是个字符串,这样拼接的"${Mapper包路径}.${Mapper类名}.${执行方法名}.${方法返回类型}",值是这个方法对应的结果处理配置。
mappedStatments保存在了configuration中。键是个字符串,这样拼接的"${Mapper包路径}.${Mapper类名}.${执行方法名}",值是这个方法对应的sql执行配置。
那这些数据何时使用呢?
在getMapper的时候,即可以取出来Mapper工厂来生成Mapper类。
当执行Mapper中某个方法时,即可以从MappedStatement中找到执行的sql数据,获得结果后,能够从ResultMap中找到定义的结果类型,将结果转为定义的类型。
后面三篇文章会分别从这三个类出发来进行讨论。代理