
binding模块
1. MapperRegistry
config:保存所有mybatis的配置信息,全局唯一,config里也绑定一个MapperRegistry,addMappers、getMappers都是由Configuration来调用
knownMapper:该集合的key是Mapper接口对应的Class对象,value为MapperProxyFactory工厂对象,可以为Mapper接口创建代理对象
void addMappers(String packageName) 扫描packageName下所有mapper接口
getMapper(Class<T> type, SqlSession sqlSession) 获取代理对象,核心代码:mapperProxyFactory.newInstance(sqlSession)
2. MapperProxyFactory
每个mapperInterface对应一个MapperProxyFactory,创造出的MapperProxy都会共用methodCache缓存,
而每个MapperProxy绑定一个SqlSession,每getMapper(Class<T> type, SqlSession sqlSession)一下就创建出一个MapperProxy,这样设计原因?
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
最后走了java动态代理Proxy.newProxyInstance ,在此之前需要初始化一个InvocationHandler接口的实现类MapperProxy
Java代理
3. MapperProxy
@Override
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)) { //java7以上静态方法、default方法也直接调用
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
//从缓存中获取MapperMethod对象,如果缓存中没有,则创建新的MapperMethod对象并添加到缓存中
//这个缓存是MapperProxyFactory工厂里的缓存
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
private MapperMethod cachedMapperMethod(Method method) {
return methodCache.computeIfAbsent(method, k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
4. MapperMethod
连接Mapper接口方法以及映射配置文件中定义的SQL 语句的桥梁。

内部类:SqlCommand
记录sql信息,主要name type两个字段
name:”com.xqw.xxxMapper.insert”,
type:”insert”
内部类:MethodSignature
boolean returnsMany; //返回值类型是否为Collection 类型或是数组类型
boolean returnsMap ; //返回值类型是否为Map 类型
boolean returnsVoid; //返回值类型是否为Void
boolean returnsCursor ; // 返回值是否为Cursor 类型
Class<?> returnType ; // 返回值类型
String mapKey; //如果返回值类型是Map ,则该字段记录了作为key的列名
Integer resultHandlerlndex; //用来标记该方法参数列表中ResultHandler 类型参数的位置
Integer rowBoundsindex ; //用来标记该方法参数列表中RowBounds 类型参数的位置
ParamNameResolver://参数解析 主要用到`Object getNamedParams(Object[] args)`方法 会返回单一对象或者name->Object 的map对象
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case /NSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE:
case DELETE:
//UPDATE、DELETE省略,和/NSERT差不多
case SELECT:
//处理返回值为void 且ResultSet 通过ResultHandler 处理的方法
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else { //处理返回值为单一对象的方法
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional() &&
(result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
execute方法最后都会调用调用SqlSession 对应的方法完成数据库操作 最后用一些rowCountResult、executeForMany方法处理返回值,转换成代理对象对应的返回值
Cache
public interface Cache {
String getId () ; // 该缓存对象的id
void putObject(Object key, Object value ); // 向缓存中添加数据,一般情况下, key 是CacheKey , value是查询结果
Object getObject(Object key); // 根据指定的key ,在缓存中查找对应的结果对象
Object removeObject(Object key); // 删除key 对应的缓存项
void clear(); // 清空缓存
int getSize();// 缓存项的个数,该方法不会被MyBatis 核心代码使用,所以可提供空实现
ReadWriteLock getReadWriteLock();//获取读写锁,该方法不会被MyBatis 核心代码使用,所以可提供空实现
}
PerpetualCache:HashMap简单实现
装饰类,都有final Cache delegate;字段,构造器都要传入被装饰类Cache
具体装饰类:
BlockingCache:
FifoCache
LoggingCache
LruCache
ScheduledCache
SerializedCache
SoftCache
SynchronizedCache
TransactionalCache 事务缓存结果集,添加缓存的时候先加到一个临时变量,事务提交后再复制到真正的缓存对象中
WeakCache