BlogMapper mapper = session.getMapper(BlogMapper.class);
mybatis中,通过session.getMapper来获取mapper接口的实现类,同样的,ctrl+alt+B 进入这个方法的默认实现
org.apache.ibatis.session.defaults.DefaultSqlSession#getMapper 中:
@Override
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}
它的实现是从全局配置类中获取mapper接口的实现:
org.apache.ibatis.session.Configuration#getMapper , 在前面的分析中,我们知道了knownMappers 保存的是mapper接口和MapperProxyFactory 之间的映射关系,因此这里先获取到了MapperProxyFactory这个工厂类,然后通过JDK动态代理创建了mapper接口的实现类:
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// 每个接口都有一个工厂类
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) 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);
}
}
动态代理创建mapper对象的过程如下:
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
// 参数1: 类加载器
// 参数2: 被代理类实现的接口
// 参数3: 实现了InvocationHandler接口的一个代理类,后面执行代理类的方法时,会走到mapperProxy的invoke方法里面!
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);
}
总结一下getMapper所做的事情:
1、 通过getmapper 获取工厂类MapperProxyFactory
2、 通过 MapperProxyFactory创建了一个代理类对象
既然是动态代理,那么必然会有一个invoke方法,如下:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// 从Object类继承的toString hashCode equals getClass等方法无需走执行sql的流程
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else {
// 提升获取mapperMethod的效率,到mapperMathodInvoker(内部接口)的invoke
// 普通方法会走到plainMethodInvoker的invoke
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
try {
// java8中的map方法,根据key获取值,如果值是null,则把后面Object的值
// 赋给key,如果获取不到,就创建,
// 虎丘的是mapperMethdoInvoker接口对象,只有一个invoke方法
return methodCache.computeIfAbsent(method, m -> {
if (m.isDefault()) {
// 接口的默认方法(java8)只要实现接口,都会继承接口的默认方法,例如List.sort()
try {
if (privateLookupInMethod == null) {
return new DefaultMethodInvoker(getMethodHandleJava8(method));
} else {
return new DefaultMethodInvoker(getMethodHandleJava9(method));
}
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
| NoSuchMethodException e) {
throw new RuntimeException(e);
}
} else {
// 普通方法返回PlainMethodInvoker
return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
});
} catch (RuntimeException re)