1.Mybatis中Mapper的使用
Mybatis除了使用SqlSession直接执行Mapper配置文件中的方法外,还可以生成Mapper接口的对象,通过Mapper对象调用接口方法也可以执行数据库操作。
在获得SqlSession之后,通过getMapper方法可以获得Mapper接口的实例,传入的参数是对应Mapper的class对象
public static void main(String[] args) {
...
session = factory.openSession();
MybatisUserMapper mybatisUserMapper = session.getMapper(MybatisUserMapper.class);
user = mybatisUserMapper.select(3);
...
}
2.SqlSession获取Mapper
从SqlSession的创建过程中了解到SqlSession的实例是DefaultSqlSession
查看DefaultSqlSession的getMapper方法,方法中实际是通过Configuration的getMapper方法获得Mapper对象,传入的参数是Mapper的class类型和SqlSession的引用
Configuration是XMLConfigBuilder解析Mybatis配置文件得到的
public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}
3.Configuration中获取Mapper
查看Configuration的getMapper方法,方法中通过mapperRegistry对象的getMapper方法获取Mapper对象
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
mapperRegistry是MapperRegistry的对象,它在Configuration的构造方法中进行初始化
protected final MapperRegistry mapperRegistry;
public Configuration() {
...
this.mapperRegistry = new MapperRegistry(this);
...
}
4.MapperRegistry中获取Mapper
MapperRegistry构造方法中给Configuration对象进行赋值,它还有另一个Map对象的属性knownMappers
public class MapperRegistry {
private final Configuration config;
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap();
public MapperRegistry(Configuration config) {
this.config = config;
}
}
在MapperRegistry的getMapper方法中,通过传入的Mapper接口的class对象到knownMappers中获取对应的MapperProxyFactory对象
然后通过MapperProxyFactory的newInstance方法创建对应的接口的实例
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);
}
}
}
5.MapperProxyFactory中生成Mapper对象
MapperProxyFactory的newInstance方法中,首先创建一个MapperProxy对象,然后调用newInstance(MapperProxy)方法创建Mapper对象
public class MapperProxyFactory<T> {
...
public T newInstance(SqlSession sqlSession) {
MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}
...
}
MapperProxy实现InvocationHandler接口,是Java动态代理中的代理类,在调用对象的方法的时候会回调invoke方法
public class MapperProxy<T> implements InvocationHandler, Serializable {
...
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
}
...
}
newInstance(MapperProxy)方法中使用动态代理模式创建Mapper实例
public class MapperProxyFactory<T> {
...
protected T newInstance(MapperProxy<T> mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
...
}
6.总结
SqlSession中获取Mapper实际上是通过SqlSession的configuration对象来获取,在Configuration类中有一个MapperRegistry对象,MapperRegistry中有一个knownMappers集合对象,里面存储了Mapper的class对象和MapperProxyFactory的对应关系,通过Mapper的class对象可以从集合中获取对应的MapperProxyFactory对象,在MapperProxyFactory中通过动态代理的模式来创建Mapper的实例
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/8236.html