MyBatis官方教程
MyBatis二级缓存设计
Mybatis中Mapper动态代理的实现原理
制作Mybatis插件---针对Mybatis的四大对象
调用SqlSession的getMapper方法 <==> MapperRegistry的getMapper方法(注册Mapper接口与获取生成代理类实例的工具类)。
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
//获取MapperProxy对象
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
}
MapperProxy类构造方法:
//sqlSession & 接口 & 接口方法
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
MapperProxy类invoke方法:从缓存中获得执行方法对应的MapperMethod类实例;如果MapperMethod类实例不存在的情况,创建加入缓存并返回相关的实例。
//接口代理对象所有的方法调用都会调用该方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
if (method.isDefault()) {
return this.invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
//缓存
MapperMethod mapperMethod = this.cachedMapperMethod(method);
//执行
return mapperMethod.execute(this.sqlSession, args);
}
MapperMethod类构造方法:SqlCommand & MethodSignature(说明方法的一些信息)。
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new MapperMethod.SqlCommand(config, mapperInterface, method);
this.method = new MapperMethod.MethodSignature(config, mapperInterface, method);
}
SqlCommand来封装底层的增删改查操作,MappedStatement的resource对应xml路径,id对应接口名+方法名。
图1-1 MappedStatement结构.pngMappedStatement创建:在SqlSessionFactory创建时,SqlSessionFactoryBuilder类build方法。MapperBuilderAssistant类的addMappedStatement方法。
图1-2 MappedStatement创建堆栈信息.pngMapperMethod类execute方法部分源码:
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
Object param;
switch(this.command.getType()) {
case INSERT:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
break;
case UPDATE:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
break;
图1-3 缓存.png
图1-4 查询流程.png
补充知识:四大对象 & 插件拦截 & 分页插件 & 批量执行 & 存储过程 & 自定义类型处理器(处理枚举)
网友评论