1、概述
Mybatis的Binding模块对应的是io包,如下图所示:
Binding模块所涉及的类如下图所示:
2. MapperRegistry
2.1 构造方法
//MyBatis Configuration 对象
private final Configuration config;
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
public MapperRegistry(Configuration config) {
this.config = config;
}
2.2 addMappers
addMappers(String packageName, ...)
方法,扫描指定包,并将符合的类,添加到 knownMappers
中。代码如下:
public void addMappers(String packageName) {
addMappers(packageName, Object.class);
}
public void addMappers(String packageName, Class<?> superType) {
// 1、 扫描指定包下的指定类
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
// 2、遍历,添加到 knownMappers 中
for (Class<?> mapperClass : mapperSet) {
addMapper(mapperClass);
}
}
先使用 ResolverUtil 扫描指定包下的指定类,在 上篇的 IO 模块中有,在通过addMapper方法添加到knowMappers中,代码如下:
public <T> void addMapper(Class<T> type) {
// 1、判断是否为接口。
if (type.isInterface()) {
// 2、 已经添加过,则抛出 BindingException 异常
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
// 3、 添加到 knownMappers 中
knownMappers.put(type, new MapperProxyFactory<>(type));
// 4、解析 Mapper 的注解配置
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
// 5、 标记加载完成
loadCompleted = true;
} finally {
// 6、若加载未完成,从 knownMappers 中移除
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
}
2.3 getMapper
getMapper(Class<T> type, SqlSession sqlSession)
方法,获得 Mapper Proxy 对象。代码如下:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// 1、获得 MapperProxyFactory 对象
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
// 不存在,则抛出 BindingException 异常
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
// 2、创建 Mapper Proxy 对象
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
<1> 处,从 knownMappers 中,获得 MapperProxyFactory 对象。
<2> 处,调用 MapperProxyFactory#newInstance(SqlSession sqlSession) 方法,创建 Mapper Proxy 对象。
3. MapperProxyFactory
org.apache.ibatis.binding.MapperProxyFactory
,Mapper Proxy 工厂类。
3.1 构造方法
//Mapper 接口
private final Class<T> mapperInterface;
//方法与 MapperMethod 的映射
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
3.2 newInstance
newInstance(...) 方法,创建 Mapper Proxy 对象。代码如下:
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
依然是稳稳的基于 JDK Proxy 实现,而 InvocationHandler 参数是 MapperProxy 对象。
4. MapperProxy
4.1 构造方法
//SqlSession 对象
private final SqlSession sqlSession;
// Mapper 接口
private final Class<T> mapperInterface;
// 方法与 MapperMethod 的映射 ,从 MapperProxyFactory的属性methodCache 传递过来
private final Map<Method, MapperMethod> methodCache;
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
4.2 invoke
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// 1、如果是 Object 定义的方法,直接调用
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
//2、判断是否为 default 修饰的方法
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
// 3、获得 MapperMethod 对象
final MapperMethod mapperMethod = cachedMapperMethod(method);
// 4、 执行 MapperMethod 方法
return mapperMethod.execute(sqlSession, args);
}
<1> 处,如果是 Object 定义的方法,直接调用。
<2> 处,调用 #isDefaultMethod((Method method) 方法,判断是否为 default 修饰的方法,若是,则调用 invokeDefaultMethod(Object proxy, Method method, Object[] args) 方法,进行反射调用。
<3> 处,调用 #cachedMapperMethod(Method method) 方法,获得 MapperMethod 对象。代码如下:
private MapperMethod cachedMapperMethod(Method method) {
return methodCache.computeIfAbsent(method, k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
<4> 处,调用 MapperMethod#execute(SqlSession sqlSession, Object[] args) 方法,执行 MapperMethod 方法。
5. MapperMethod
org.apache.ibatis.binding.MapperMethod
,Mapper 方法。在 Mapper 接口中,每个定义的方法,对应一个 MapperMethod 对象。
5.1 构造方法
// SqlCommand 对象
private final SqlCommand command;
// MethodSignature 对象
private final MethodSignature method;
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, mapperInterface, method);
}
command 属性,SqlCommand 对象,是 MapperMethod 的内部静态类,SQL 命令。
method 属性,MethodSignature 对象,是 MapperMethod 的内部静态类,方法签名。
5.2 execute
这个方法涉及到执行一个Sql命令的完整流程,所以另起一篇续写。