现在我们已经有一个DefaultSqlSession 了,必须找到Mapper.xml 里面定义的Statement ID,才能执行对应的SQL 语句。
找到Statement ID 有两种方式:一种是直接调用session 的方法,在参数里面传入Statement ID,这种方式属于硬编码,我们没办法知道有多少处调用,修改起来也很麻烦。
另一个问题是如果参数传入错误,在编译阶段也是不会报错的,不利于预先发现问题。
Blog blog = (Blog) session.selectOne("com.leon.mapper.BlogMapper.selectBlogById
", 1);
所以在MyBatis 后期的版本提供了第二种方式,就是定义一个接口,然后再调用Mapper 接口的方法。
由于我们的接口名称跟Mapper.xml 的namespace 是对应的,接口的方法跟statement ID 也都是对应的,所以根据方法就能找到对应的要执行的SQL。
BlogMapper mapper = session.getMapper(BlogMapper.class);
在这里我们主要研究一下Mapper 对象是怎么获得的,它的本质是什么。
DefaultSqlSession 的getMapper()方法,调用了Configuration 的getMapper()方法。
configuration.<T>getMapper()
Configuration 的getMapper()方法,又调用了MapperRegistry 的getMapper()方法。
mapperRegistry.getMapper()
我们知道,在解析mapper 标签和Mapper.xml 的时候已经把接口类型和类型对应的MapperProxyFactory 放到了一个Map 中。获取Mapper 代理对象,实际上是从Map 中获取对应的工厂类后,调用以下方法创建对象:
MapperProxyFactory.newInstance()
最终通过代理模式返回代理对象:
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]
{ mapperInterface }, mapperProxy);
回答了前面的问题:为什么要保存一个工厂类,它是用来创建代理对象的。