解析下面这两行代码,暂且不考虑和spring结合:
// 通过sqlSession执行SQL语句
IMessage imessage = sqlSession.getMapper(IMessage.class);
messageList = imessage.queryMessageList(parameter);
第一步:为接口产生一个代理类
sqlSession 实现类 DefaultSqlSession
public T getMapper(Class type, SqlSession sqlSession) {
MapperProxyFactory mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
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);
}
}
}
那么knownMappers又是在哪初始化的呢?
//加载xml配置文件的时候会调用这个方法
public void addMapper(Class type) {
...省略...
try {
//关键put方法
this.knownMappers.put(type, new MapperProxyFactory(type));
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
this.knownMappers.remove(type);
}
}
}
}
MapperProxyFactory.java的源码
上面getMapper方法里面调用的 mapperProxyFactory.newInstance(sqlSession);
实际上就是生成一个接口的动态代理类
public class MapperProxyFactory {
private final Class mapperInterface;
private Map methodCache = new ConcurrentHashMap();
public MapperProxyFactory(Class mapperInterface) {
this.mapperInterface = mapperInterface;
}
...省略...
protected T newInstance(MapperProxy mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
MapperProxy mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}
}
第二步:调用代理方法
执行接口的代理类的方法 == invokeHandler的invoke方法
这似乎动态代理的知识
public class MapperProxy implements InvocationHandler
//估计加载配置的时候,把这个类初始化好
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//因为传进去的是接口,不是object,实体类的父类应该是object,不会执行
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
//这个是主要方法
final MapperMethod mapperMethod = cachedMapperMethod(method);
//信息查找完毕,开始执行
return mapperMethod.execute(sqlSession, args);
}
private MapperMethod cachedMapperMethod(Method method) {
MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) {//初始化的时候没传值,肯定会走这一句
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
下面看看初始化MapperMethod的代码
public MapperMethod(Class> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, method);
}
初始化了一个SqlCommond
public static class SqlCommand {
//这两个属性至关重要,后面执行,要用到这两个属性
private final String name;
private final SqlCommandType type;
public SqlCommand(Configuration configuration, Class> mapperInterface, Method method) throws BindingException {
//把拼接好的namespace.id 拿到配置文件里面去查找
String statementName = mapperInterface.getName() + "." + method.getName();
MappedStatement ms = null;
if (configuration.hasStatement(statementName)) {
//查询结果放在MappedStatement 这个类很关键
ms = configuration.getMappedStatement(statementName);
} else if ...省略...
name = ms.getId();
type = ms.getSqlCommandType();
...省略...
既然都查到关键信息
name == namespace.id)
SqlCommandType == 执行类型
下一步就开始执行呗
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
...省略...
(SqlCommandType.SELECT == command.getType()) {
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 {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
}