Mybatis源码分析获取Mapper
2016-04-01 17:43
393 查看
这次分析的入口是
根据上篇分析我们这里获得的sqlSession是DefaultSqlSession,
1.我们进入getMapper方法
这里没有做什么处理,接下来进入configuration.getMapper中
利用我们开始解析xml获得的mapperRegistry获取,继续跟进
这里就要说一下什么是MapperProxyFactory?
翻译成中文就是映射代理工厂。
上面构造函数的代码首先会把之前在mapper.xml中配置的那些mapper接口注入进去,这里我们也会有一个方法缓存,我们每个方法都会对应一个MapperMethod其中保存我们已经解析过的sql。接下来我们就会生成我们的代理映射类。
mapperProxy就是我们的代理类,接下来进入我们的代理类之中。Mybatis实现的是Jdk动态代理,在代理之中最重要的当然是invoke,接下来我们分析。
1.上面的invoke之中我们首先判断method方法的拥有者类是不是和object.class相等。如果相等就直接执行Invoke。
2.如果不相等通过this.cachedMapperMethod(method);获取我们该方法的缓存映射。
3。调用mapperMethod.execute(this.sqlSession, args); 这是真正的执行过程。
这里MapperMethod非常重要我们这里详细分析:
在MapperMethod维护了两个变量SqlCommand 和MethodSignature ,SqlCommand类获取处理的唯一标识及SQL语句类型,MethodSignature类对业务接口方法的入参类型及出参类型进行处理。
在SqlCommand的构造函数中有
当我们代理实例生成之后,我们利用jdk反射Proxy.newProxyInstance()方法生成我们的代理类。
至此我们获取Mapper过程全部分析完毕。简而言之就是生成了利用Proxy动态代理反射生成。
StudentMapper studentMapper=sqlSession.getMapper(StudentMapper.class);
根据上篇分析我们这里获得的sqlSession是DefaultSqlSession,
public class DefaultSqlSession implements SqlSession { private Configuration configuration; private Executor executor; private boolean autoCommit; private boolean dirty; public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) { this.configuration = configuration; this.executor = executor; this.dirty = false; this.autoCommit = autoCommit; } }
1.我们进入getMapper方法
public <T> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); }
这里没有做什么处理,接下来进入configuration.getMapper中
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return this.mapperRegistry.getMapper(type, sqlSession); }
利用我们开始解析xml获得的mapperRegistry获取,继续跟进
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap();//这是我们mapperRegistry中保存的 public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);//通过上面的HashMap获取mapperProxyFactory if(mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try { return mapperProxyFactory.newInstance(sqlSession);//生成代理类 } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } }
这里就要说一下什么是MapperProxyFactory?
翻译成中文就是映射代理工厂。
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap(); public MapperProxyFactory(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; }
上面构造函数的代码首先会把之前在mapper.xml中配置的那些mapper接口注入进去,这里我们也会有一个方法缓存,我们每个方法都会对应一个MapperMethod其中保存我们已经解析过的sql。接下来我们就会生成我们的代理映射类。
public T newInstance(SqlSession sqlSession) { MapperProxy mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance((MapperProxy)mapperProxy); }
mapperProxy就是我们的代理类,接下来进入我们的代理类之中。Mybatis实现的是Jdk动态代理,在代理之中最重要的当然是invoke,接下来我们分析。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(Object.class.equals(method.getDeclaringClass())) { try { return method.invoke(this, args); } catch (Throwable var5) { throw ExceptionUtil.unwrapThrowable(var5); } } else { MapperMethod mapperMethod = this.cachedMapperMethod(method); return mapperMethod.execute(this.sqlSession, args); } } private MapperMethod cachedMapperMethod(Method method) { MapperMethod mapperMethod = (MapperMethod)this.methodCache.get(method); if(mapperMethod == null) { mapperMethod = new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration()); this.methodCache.put(method, mapperMethod); } return mapperMethod; }
1.上面的invoke之中我们首先判断method方法的拥有者类是不是和object.class相等。如果相等就直接执行Invoke。
2.如果不相等通过this.cachedMapperMethod(method);获取我们该方法的缓存映射。
3。调用mapperMethod.execute(this.sqlSession, args); 这是真正的执行过程。
这里MapperMethod非常重要我们这里详细分析:
public class MapperMethod { private final MapperMethod.SqlCommand command; private final MapperMethod.MethodSignature method; public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) { this.command = new MapperMethod.SqlCommand(config, mapperInterface, method); this.method = new MapperMethod.MethodSignature(config, method); } }
在MapperMethod维护了两个变量SqlCommand 和MethodSignature ,SqlCommand类获取处理的唯一标识及SQL语句类型,MethodSignature类对业务接口方法的入参类型及出参类型进行处理。
在SqlCommand的构造函数中有
public static class SqlCommand { private final String name;//保存我们唯一标识id private final SqlCommandType type;//保存我们sql语句类型 public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) { String statementName = mapperInterface.getName() + "." + method.getName(); MappedStatement ms = null; if(configuration.hasStatement(statementName)) { ms = configuration.getMappedStatement(statementName); } else if(!mapperInterface.equals(method.getDeclaringClass())) { String parentStatementName = method.getDeclaringClass().getName() + "." + method.getName(); if(configuration.hasStatement(parentStatementName)) { ms = configuration.getMappedStatement(parentStatementName); } } if(ms == null) { if(method.getAnnotation(Flush.class) == null) { throw new BindingException("Invalid bound statement (not found): " + statementName); } this.name = null; this.type = SqlCommandType.FLUSH; } else { this.name = ms.getId(); this.type = ms.getSqlCommandType(); if(this.type == SqlCommandType.UNKNOWN) { throw new BindingException("Unknown execution method for: " + this.name); } } } }
当我们代理实例生成之后,我们利用jdk反射Proxy.newProxyInstance()方法生成我们的代理类。
protected T newInstance(MapperProxy<T> mapperProxy) { return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); }
至此我们获取Mapper过程全部分析完毕。简而言之就是生成了利用Proxy动态代理反射生成。
相关文章推荐
- android shape的使用
- 微信支付插件使用
- Android ActionBar应用实战,高仿微信主界面的设计
- 通过包名,直接精确启动一个三方Activity
- Android 5.0 CardView+ListView 卡片布局应用
- 关于 Unity 中 ModelImporter.optimizeGameObjects
- 让Xcode的 stack trace信息可读
- 【Dialer】android6.0拨号界面分析<一>
- 使用MySQL+DataMapper为Ruby Web应用增加数据库存储
- 执行命令行并等待完成(使用WaitForSingleObject达到目的)
- iOS 9已下的获取APP进程信息
- Swift 学习记录(4)
- iOS 解析json串
- Android fragment 重叠问题的解决方法
- 在Android Studio中有六种依赖
- iOS多线程
- nrf51822微信---AES加密
- iOS多线程编程技术之NSThread、Cocoa NSOperation、GCD
- 【Android 2D 游戏开发(4)】——俄罗斯方块(手势操作)
- Android NestedScrolling与分发机制 二