在使用Mybatis開(kāi)發(fā)中思喊,或者和Spring整合中垃沦,在Dao層中的Mapper接口對(duì)xml中的sql對(duì)應(yīng)著艘儒,在service中直接調(diào)用Dao中的方法達(dá)到訪問(wèn)sql,如下:
這是一個(gè)Mapper的接口
public interface ActivityCzMapper {
ActivityCz selectByPrimaryKey(Integer id);
}
xml中對(duì)應(yīng)的sql
...
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from activity_cz
where id = #{id,jdbcType=INTEGER}
</select>
...
ActivityCzMapper 接口并沒(méi)有實(shí)現(xiàn)類(lèi)异袄,那是如何調(diào)用的sql呢咱枉?可以在源碼中學(xué)習(xí)
在MyBatis中調(diào)用一個(gè)sql時(shí)候,sqlSession.selectList(""); 在這之前通過(guò)SqlSessionFactoryBuilder的build("MYbatis配置文件")出的sqlsession球昨。
Mybatis調(diào)用接口中方法時(shí)如下
ActivityCzMapper am = sqlSession.getMapper(ActivityCzMapper.class);
ActivityCz activityCz = am.selectByPrimaryKey(1);
我們查看org.apache.ibatis下的session的DefaultSqlSession代碼的getMapper方法
DefaultSqlSession.class文件
...
public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}
...
繼續(xù)找getMapper方法尔店,在Configuration.class中
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
注意這里getMapper(type, sqlSession)方法里的type是一直傳遞的Mapper接口類(lèi),sqlSession是上面的DefaultSqlSession實(shí)例主慰。繼續(xù)跳到MapperRegistry.class中的getMapper(type,sqlSession)方法中
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);
}
}
}
這里首先看return的東西嚣州,是一個(gè)mapperProxyFactory的 newInstance實(shí)例,那么可以猜想是利用動(dòng)態(tài)代理模式共螺,繼續(xù)看mapperProxyFactory是從哪里來(lái)的该肴,可以看到這行代碼: MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); 通過(guò)knownMappers一個(gè)map 得到的--因?yàn)樵陬?lèi)MapperRegistry中定義了private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap()這個(gè)map,
knownMappers中g(shù)et的key是我們傳來(lái)的Mapper接口(最上面示例的ActivityCzMapper ),那說(shuō)明這個(gè)map在我們getMapper方法之前應(yīng)該add過(guò)藐不,在類(lèi)MapperRegistry下面可以看到代碼:
public <T> void addMapper(Class<T> type) {
if(type.isInterface()) {
if(this.hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
this.knownMappers.put(type, new MapperProxyFactory(type));
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
parser.parse();
loadCompleted = true;
} finally {
if(!loadCompleted) {
this.knownMappers.remove(type);
}
}
}
}
發(fā)現(xiàn)了add里面具體的就不看匀哄,重點(diǎn)有一句代碼this.knownMappers.put(type, new MapperProxyFactory(type));
可以理解這里的type就是我們的Mapper接口,把他當(dāng)成key雏蛮,put到map中涎嚼。
這里我們?cè)倩氐組apperRegistry.class中的getMapper(type,sqlSession)方法中,找到return mapperProxyFactory.newInstance(sqlSession)的東西
跳到MapperProxyFactory.class中挑秉,可以看到代碼
public T newInstance(SqlSession sqlSession) {
MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}
看到這個(gè)方法里法梯,new了一個(gè)MapperProxy的構(gòu)造方法,里面有三個(gè)參數(shù)犀概,第一個(gè)sqlSession是我前面提起的DefaultSqlSession立哑,第二個(gè)mapperInterface是MapperProxyFactory.class中的定義的成員變量,就是我們傳的Mapper接口阱冶,在我們前面找到的addMapper(Class<T> type) 方法中那個(gè)knownMappers的map的value值刁憋。第三個(gè)參數(shù)是一個(gè)初始化的ConcurrentHashMap在類(lèi)中這樣定義
private Map<Method, MapperMethod> methodCache = new ConcurrentHashMap();
是空的。
注意下這個(gè)方法中new的MapperProxy類(lèi)木蹬,這個(gè)類(lèi)
public class MapperProxy<T> implements InvocationHandler, Serializable {
...
}
他實(shí)現(xiàn)了InvocationHandler至耻,說(shuō)明利用了JDK的動(dòng)態(tài)代理若皱,把三個(gè)參數(shù)初始化的MapperProxy代理類(lèi)傳到下一個(gè)重載方法。
繼續(xù)找到當(dāng)前類(lèi)的newInstance的重載方法
protected T newInstance(MapperProxy<T> mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
到這里就可以知道了利用jdk的動(dòng)態(tài)代理模式Proxy.newProxyInstance方法尘颓,里面的三個(gè)參數(shù)顯而易見(jiàn)走触,對(duì)于第三個(gè)參數(shù)mapperProxy就是 實(shí)現(xiàn)了InvocationHandler接口的MapperProxy類(lèi)。