@Override
public T getMapper(Class type) {
return configuration.getMapper(type, this);
}
public T getMapper(Class type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
MapperProxyFactory类型,然后调用mapperProxyFactory.newInstance(sqlSession)方法,创建mapper的实例。
public class MapperRegistry {
private final Configuration config;
/**
* 已知的Mapper集合,有添加mapper的方法,通过添加方法,将所有的Mapper接口添加到已知集合里
* key:Mapper接口的class对象
* value:MapperProxyFactory,从名字上看是一个mapper代理工厂
*/
private final Map, MapperProxyFactory>> knownMappers = new HashMap, MapperProxyFactory>>();
public MapperRegistry(Configuration config) {
this.config = config;
}
@SuppressWarnings("unchecked")
public T getMapper(Class type, SqlSession sqlSession) {
//根据Class类型从已知的mapper集合中查找
final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) knownMappers.get(type);
//如果查找失败抛出异常
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//动态代理创建一个mapper的实例
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
public boolean hasMapper(Class type) {
return knownMappers.containsKey(type);
}
/**
* 添加mapper
* @param type
* @param
*/
public void addMapper(Class type) {
//如果是个接口
if (type.isInterface()) {
//如果已经存在
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
//将mapper放入knownMappers中
knownMappers.put(type, new MapperProxyFactory(type));
// It's important that the type is added before the parser is run
// otherwise the binding may automatically be attempted by the
// mapper parser. If the type is already known, it won't try.
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
}
/**
* @since 3.2.2
*/
public Collection> getMappers() {
return Collections.unmodifiableCollection(knownMappers.keySet());
}
/**
* @since 3.2.2
*/
public void addMappers(String packageName, Class> superType) {
ResolverUtil> resolverUtil = new ResolverUtil>();
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set>> mapperSet = resolverUtil.getClasses();
for (Class> mapperClass : mapperSet) {
addMapper(mapperClass);
}
}
/**
* 通过扫描包名向knownMappers添加mapper
* @since 3.2.2
*/
public void addMappers(String packageName) {
addMappers(packageName, Object.class);
}
}
(4)MapperProxyFatory的newInstance方法
调用newInstance(sqlSession)方法时,会生成一个MapperProxy对象,从名字就能看出,这就是Mapper的代理类,然后再调用Proxy.newProxyInstance完成代理对象的实例化。
public class MapperProxyFactory {
private final Class mapperInterface;
private final Map methodCache = new ConcurrentHashMap();
public MapperProxyFactory(Class mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class getMapperInterface() {
return mapperInterface;
}
public Map getMethodCache() {
return methodCache;
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy mapperProxy) {
/**
* 使用动态代理实例化代理对象
* 三个参数:
* 1:指明生成代理对象使用哪个类加载器
* 2:指明生成哪个对象的代理对象,通过接口指定
* 3:代理对象,MapperProxy实现了InvocationHandler接口
*/
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
//创建一个 MapperProxy对象
final MapperProxy mapperProxy = new MapperProxy(sqlSession, mapperInterface, methodCache);
//使用动态代理实例化对象
return newInstance(mapperProxy);
}
}
(5)mapper的实际代理对象MapperProxy
可以看出MapperProxy实现了InvocationHandler接口,重写了invoke方法。
调用Mapper中的方法时,会调用invoke方法,invoke方法需要三个参数,proxy指的是代理对象,method指的是调用被代理对象中的方法,args是方法的参数。
在inoke方法中,通过方法获取方法所在类的class信息,如果是个接口,会将被调用的方法封装为一个MapperMethod对象,然后调用它的execute方法。
/**
* mapper的代理类
*/
public class MapperProxy implements InvocationHandler, Serializable {
private static final long serialVersionUID = -6424540398559729838L;
private final SqlSession sqlSession;
private final Class mapperInterface;
/**
* 方法缓存集合,当调用接口中的方法时,会将封装一个MapperMethod对象做为value,方法作为key,放入集合中
*/
private final Map methodCache;
public MapperProxy(SqlSession sqlSession, Class mapperInterface, Map methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
/**
* 通过动态代理调用被代理对象的方法时,实际走的是invoke方法,在invoke方法中通过method.invoke方式完成方法的调用
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {//是否是类
return method.invoke(this, args);//如果是类直接通过反射技术调用类中的方法
} else if (isDefaultMethod(method)) {//是否是默认的方法
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
//如果是接口,通过cachedMapperMethod方法完成MapperMethod的实例化
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
private MapperMethod cachedMapperMethod(Method method) {
MapperMethod mapperMethod = methodCache.get(method);
//如果不在方法缓存中
if (mapperMethod == null) {
//创建一个MapperMethod对象
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
@UsesJava7
private Object invokeDefaultMethod(Object proxy, Method method, Object[] args)
throws Throwable {
final Constructor constructor = MethodHandles.Lookup.class
.getDeclaredConstructor(Class.class, int.class);
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
final Class> declaringClass = method.getDeclaringClass();
return constructor
.newInstance(declaringClass,
MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED
| MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC)
.unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args);
}
/**
* 默认的方法
*/
private boolean isDefaultMethod(Method method) {
return (method.getModifiers()
& (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC
&& method.getDeclaringClass().isInterface();
}
}
(6)MapperMethod类
MapperMethod构造函数中会对SqlCommand对象和MethodSignature对象初始化。SqlCommand中封装了SQL命令类型以及方法的名称(XML中配置的id+Mapper所在接口路径),MethodSignature中封装了方法参数、返回类型等信息。
在SqlCommand初始化时,又根据接口和调用的方法信息创建了MappedStatement对象,封装了XML当中标签的信息。
执行MapperMethod的execute方法时先判断SQL命令类型(增删改查等),然后调用的是SqlSession中的方法执行SQL命令。
public class MapperMethod {
/**
* 封装了SQL命令类型(增删改查等)
*/
private final SqlCommand command;
/**
* 封装了方法参数、返回类型等信息
*/
private final MethodSignature method;
/**
* 构造函数
* @param mapperInterface
* @param method
* @param config
*/
public MapperMethod(Class> mapperInterface, Method method, Configuration config) {
//初始化SqlCommand
this.command = new SqlCommand(config, mapperInterface, method);
//初始化MethodSignature
this.method = new MethodSignature(config, mapperInterface, method);
}
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
//判断SQL标签类型
switch (command.getType()) {
case INSERT: {//插入
Object param = method.convertArgsToSqlCommandParam(args);//处理参数
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {//更新
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {//删除
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT://查找
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {//返回多条数据
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {//返回类型是Map
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {//返回游标
result = executeForCursor(sqlSession, args);
} else {//返回单行数据
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
......
/**
* 返回多条数据的查询方法
* @param sqlSession
* @param args
* @param
* @return
*/
private Object executeForMany(SqlSession sqlSession, Object[] args) {
List result;
//处理参数
Object param = method.convertArgsToSqlCommandParam(args);
if (method.hasRowBounds()) {//如果是分页查询
RowBounds rowBounds = method.extractRowBounds(args);
//调用sqlSession的方法执行查询
result = sqlSession.selectList(command.getName(), param, rowBounds);
} else {
result = sqlSession.selectList(command.getName(), param);
}
// issue #510 Collections & arrays support
if (!method.getReturnType().isAssignableFrom(result.getClass())) {
if (method.getReturnType().isArray()) {
return convertToArray(result);
} else {
return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
}
}
return result;
}
......
public static class SqlCommand {
/**
* XML标签中ID + Mapper所在类/接口的路径
*/
private final String name;
/**
* SQL命令类型
* 包含了UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH;
*/
private final SqlCommandType type;
/**
* 构造函数
* @param configuration
* @param mapperInterface
* @param method
*/
public SqlCommand(Configuration configuration, Class> mapperInterface, Method method) {
final String methodName = method.getName();//方法名
final Class> declaringClass = method.getDeclaringClass();//方法所在类/接口的class对象
//创建MappedStatement对象,这个对象封装了XML当中标签的信息
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);
}
}
}
public String getName() {
return name;
}
public SqlCommandType getType() {
return type;
}
private MappedStatement resolveMappedStatement(Class> mapperInterface, String methodName,
Class> declaringClass, Configuration configuration) {
//statementId,是方法名+类/接口的完整路径 eg:org.mybatis.example.BlogMapper.selectBlog
String statementId = mapperInterface.getName() + "." + methodName;
//如果Configuration中已经存在
if (configuration.hasStatement(statementId)) {
//直接从初始化阶段生成的mappedStatements中,获取当前SQL语句的mappedStatement
return configuration.getMappedStatement(statementId);
} else if (mapperInterface.equals(declaringClass)) {
/*
* mapperInterface如果是接口应该是interface 包名.接口名,declaringClass是包名.接口名
* 还不清楚什么情况下mapperInterface和declaringClass相同,反正就是如果它们两个相同就返回null
*/
return null;
}
//如果初始化阶段还没有加载过,找到当前方法所在的接口,getInterfaces()获取这个对象实现的所有接口
for (Class> superInterface : mapperInterface.getInterfaces()) {
if (declaringClass.isAssignableFrom(superInterface)) {
//生成MappedStatement
MappedStatement ms = resolveMappedStatement(superInterface, methodName,
declaringClass, configuration);
if (ms != null) {
return ms;
}
}
}
return null;
}
}
public static class MethodSignature {
private final boolean returnsMany;//返回多条结果
private final boolean returnsMap;//返回Map
private final boolean returnsVoid;//返回空
private final boolean returnsCursor;//返回游标
private final Class> returnType;//返回类型
private final String mapKey;
private final Integer resultHandlerIndex;//resultHandler类型参数的位置
private final Integer rowBoundsIndex;//rowBound类型参数的位置
private final ParamNameResolver paramNameResolver;//参数处理类
public MethodSignature(Configuration configuration, Class> mapperInterface, Method method) {
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class>) {
this.returnType = (Class>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {
this.returnType = (Class>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
......
private Integer getUniqueParamIndex(Method method, Class> paramType) {
Integer index = null;
final Class>[] argTypes = method.getParameterTypes();
for (int i = 0; i < argTypes.length; i++) {
if (paramType.isAssignableFrom(argTypes[i])) {
if (index == null) {
index = i;
} else {
throw new BindingException(method.getName() + " cannot have multiple " + paramType.getSimpleName() + " parameters");
}
}
}
return index;
}
private String getMapKey(Method method) {
String mapKey = null;
if (Map.class.isAssignableFrom(method.getReturnType())) {
final MapKey mapKeyAnnotation = method.getAnnotation(MapKey.class);
if (mapKeyAnnotation != null) {
mapKey = mapKeyAnnotation.value();
}
}
return mapKey;
}
}
}
参考:
Mybatis中Mapper动态代理的实现原理
mybatis源码分析5 - mapper读写数据库完全解析
Java基础加强总结(三)——代理(Proxy)