下面是mapper接口代理的生成逻辑
进入源码
进入getMapper看看
调用configuration的getMapper() 那么mapperRegistry是什么呢?我们看下
MapperRegistry含有两个属性。configuratio和Map。Map的key是class,value是MapperProxyFactory。那么,这个MapperProxyFactory又是什么呢? 看到该类的属性,一个Class对象,即是我们定义的Mapper接口类。一个Map来表示方法缓存。看到2个newInstance方法,立马想到应该是创建代理了。点开这两个方法 根据给定的sqlsession和接口和方法缓存创建一个mapperProxy。该类实现了InvocationHandler。那么 我们进入到其invoke()方法 该方法首先判断方法是否的Object类的方法,如果是,则不执行代理,直接进行。如果不是,执行cachedMapperMethod 方法 并调用返回对象 MapperMethod 的execute 方法。我们看看cachedMapperMethod方法,应该和缓存有关.
private MapperMethod cachedMapperMethod(Method method) {
return methodCache.computeIfAbsent(method, k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
复制代码
看下 MapperMethod的构造方法,构造了SqlCommand和MethodSignature两个对象。它们都是MapperMethod的静态内部类。
SqlCommand类有2个属性,它们是怎么得到的呢?从resolveMappedStatement()方法的返回值得到的。我们进入该方法看下
public static class SqlCommand {
private final String name;//表示sql语句的名称
private final SqlCommandType type;//表示sql语句的类型
public SqlCommand(Configuration configuration, Class> mapperInterface, Method method) {
final String methodName = method.getName();
final Class> declaringClass = method.getDeclaringClass();
MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
configuration);
if (ms == null) {
if(method.getAnnotation(Flush.class) != null){
name = null;
type = SqlCommandType.FLUSH;
} else {
throw new BindingException("Invalid bound statement (not found): "
+ mapperInterface.getName() + "." + methodName);
}
} else {
name = ms.getId();
type = ms.getSqlCommandType();
if (type == SqlCommandType.UNKNOWN) {
throw new BindingException("Unknown execution method for: " + name);
}
}
}
private MappedStatement resolveMappedStatement(Class> mapperInterface, String methodName,
Class> declaringClass, Configuration configuration) {
//获取id
String statementId = mapperInterface.getName() + "." + methodName;
if (configuration.hasStatement(statementId)) {
return configuration.getMappedStatement(statementId);
} else if (mapperInterface.equals(declaringClass)) {
return null;
}
for (Class> superInterface : mapperInterface.getInterfaces()) {
if (declaringClass.isAssignableFrom(superInterface)) {
MappedStatement ms = resolveMappedStatement(superInterface, methodName,
declaringClass, configuration);
if (ms != null) {
return ms;
}
}
}
return null;
}
复制代码
SqlCommandType是枚举。
拿到mapperMethod,进入excute();
此时返回代理对象
public MapperMethod(Class> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, mapperInterface, method);
}
复制代码
my.oschina.net/heweipo/blo…
通过上面的代码,我们拿到了代理。那么,如何用这个代理呢?利用这个代理会代理到什么方法上呢?
那么既然有了 MapperProxy 对象,只要在这个对象的invoke方法里调用执行 SQL 语句就达到目的了,因此也就不需要接口实现类了