mybatis通过jdk动态代理的原理
关键字:MapperRegistry .getMapper、mapperProxyFactory.newInstance、MapperProxy、InvocationHandler
使用Configuration的getMapper方法时,会调用mapperRegistry.getMapper方法,
public class MapperRegistry {
private final Configuration config;
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap();
public MapperRegistry(Configuration config) {
this.config = config;
}
// 看这里!
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory<T> 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);
}
}
}
而该方法又会调用**mapperProxyFactory.newInstance(sqlSession)**来生成一个具体的代理,
public class MapperProxyFactory<T> {
...
// 这个是自己用用的哈
protected T newInstance(MapperProxy<T> mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
// 这个实例方法才是对外的,返回是一个泛型,生成具体的MapperProxy的
public T newInstance(SqlSession sqlSession) {
MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}
}
该MapperProxy类实现了InvocationHandler接口,并且实现了该接口的invoke方法,完成后续的一系列sql操作,并返回映射后的Java类
public class MapperProxy<T> implements InvocationHandler, Serializable {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
if (this.isDefaultMethod(method)) {
return this.invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
}