1. 程式人生 > >mybatis(三)部分原始碼解析

mybatis(三)部分原始碼解析

1.問題一為什麼mybatis可以只定義dao介面(不涉及spring的情況下)即以下程式碼

public interface CityDao {
    List<City> listCity();
}

從SqlSession的<T> T getMapper(Class<T> type);方法入手,SqlSession的實現類DefaultSqlSession

  // DefaultSqlSession.java
  @Override
  public <T> T getMapper(Class<T> type) {
    
return configuration.<T>getMapper(type, this); } // Configuration.java public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); } // MapperRegistry.java 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 { return mapperProxyFactory.newInstance(sqlSession); }
catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } } // mapperProxyFactory 是如何附值的呢,需要看下knownMappers,這個add方法是載入配置時賦值的這裡不再贅述 public <T> void addMapper(Class<T> type) { if (type.isInterface()) { if (hasMapper(type)) { throw new BindingException("Type " + type + " is already known to the MapperRegistry."); } boolean loadCompleted = false; try { knownMappers.put(type, new MapperProxyFactory<T>(type)); // It's important that the type is added before the parser is run // otherwise the binding may automatically be attempted by the // mapper parser. If the type is already known, it won't try. MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); loadCompleted = true; } finally { if (!loadCompleted) { knownMappers.remove(type); } } } } // MapperProxyFactory<T>.java public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); } // 最後生成動態代理類 @SuppressWarnings("unchecked") protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); }