MyBatis 中 查看源码, 首先是SqlSessionFactoryBuilder 创建出SqlSessionFactory,然后从SqlSessionFactory中得到SqlSession,最后通过SqlSession得到Mapper接口对象进行数据库操作
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
通过跟踪SqlSessionFactoryBuilder源码
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { // 通过XMLConfigBuilder 类进行解析 传进来的 mybatis-config.xml 配置文件 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); // 解析之后,把值传给build方法 return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } }
然后 在通过 XMLConfigBuilder 对读取mybatis-config.xml的文件进行解析,然后 调用 DefaultSqlSessionFactory
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
继续往下跟,DefaultSqlSessionFactory 的 openSession()方法,参数 是 Configuration 对象
private final Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; }
再通过构造方法把值传给Configuration 对象解析解析,接下来我们看看Configuration对象类,内容太多了,把主要列出来 ,看看 这个 接口都干了什么
public class Configuration { protected Environment environment;
protected Class<?> configurationFactory; protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
}
看看熟悉不熟悉,这个里面 的 Envirobnment 这个 就是为了解析 mybatis-config.xml 中的标签<configuration>,这个就是 MapperRegistry 这都是 把我们写mapper接口进行注册绑定
通过上面我们阅读源码 调用openSessionFromDataSource()方法,方面里面执行解析配置文件,而且都定义为final类型,说明这个方法只在程序刚运行的时候加载一次
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
接下来继续看通过sqlSessionFactory创建SqlSession获取getMapper,参数为繁星目标对象,
/** * Retrieves a mapper. * @param <T> the mapper type * @param type Mapper interface class * @return a mapper bound to this SqlSession */ <T> T getMapper(Class<T> type);
看这个类的实现类方法,返回的是通过configuration对象中在去获取getMapper的
@Override public <T> T getMapper(Class<T> type) { return configuration.getMapper(type, this); }
在继续跟configuration.getMapper(type, this); 看看这就是通过刚才上面对配置文件加载注册到 MapperRegistry对象中,
在通过 mapperRegistry.getMapper(type, sqlSession)来获取注册过绑定的接口
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); }
继续跟进 mapperRegistry.getMapper(type, sqlSession);实现如下,看到如下枉然大悟,
@SuppressWarnings("unchecked") public <T> T getMapper(Class<T> type, SqlSession sqlSession) { //通过MapperProxyFactory<T>对象获取type final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); //判断配置文件中有没有,先前注册好的 mapper接口,要是没有就是报错 if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } try { //要是有之前mapper 注册过的 接口,就会在这里生成一个新的实例 mapperProxyFactory.newInstance(sqlSession); return mapperProxyFactory.newInstance(sqlSession); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } }
看看MapperProxyFactory 对象,通过jdk代理生成
public class MapperProxyFactory<T> { private final Class<T> mapperInterface; private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>(); public MapperProxyFactory(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; } public Class<T> getMapperInterface() { return mapperInterface; } public Map<Method, MapperMethod> getMethodCache() { return methodCache; } @SuppressWarnings("unchecked") protected T newInstance(MapperProxy<T> mapperProxy) { //看看这代码熟悉不,这就是平时所用的jdk 代码 return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } public T newInstance(SqlSession sqlSession) { //生成新的实例对象,以及缓存 final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); } }
分析 MapperProxy代理类,跟进去首先是一个带参构造方法,如下:
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) { this.sqlSession = sqlSession; this.mapperInterface = mapperInterface; this.methodCache = methodCache; }
然后还有 invoke方法
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } else if (method.isDefault()) { return invokeDefaultMethod(proxy, method, args); } } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } //从缓存mapper方法中寻找 final MapperMethod mapperMethod = cachedMapperMethod(method); //然后执行mapperMethod.execute(sqlSession, args) return mapperMethod.execute(sqlSession, args); }
在来看看 mapperMethod.execute(sqlSession, args) ,这个方法就是最终判断传入是
INSERT、UPDATE、DELETE 、SELECT 等判断, 决定执行sql语句
public Object execute(SqlSession sqlSession, Object[] args) { Object result; switch (command.getType()) { case INSERT: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); break; } case UPDATE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); break; } case DELETE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); break; } case SELECT: if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); } else if (method.returnsCursor()) { result = executeForCursor(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) { result = Optional.ofNullable(result); } } break; case FLUSH: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; }
然后在把查询数据库的result ,返回回去,这就是mybatis 一个完整的执行过程