MyBatis 源码分析-02-生成实例MapperProxy 代理对象
说明:
version :
MyBatis : 3.5.5
项目地址 :MyBatis-source-learn
示例代码:
- createSqlSession.java
public static void main(String[] args) {
DataSource dataSource = getDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
SqlSession sqlSession = sqlSessionFactory.openSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(1);
System.out.println(blog);
}
源码分析:
- 解析 获取SqlSession的过程:
- SqlSession sqlSession = sqlSessionFactory.openSession();
调用过程:
1. SqlSession sqlSession = sqlSessionFactory.openSession();
2. DefaultSqlSessionFactory.openSession();
2.1 DefaultSqlSessionFactory.openSessionFromDataSource();
2.1.1 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
2.1.2 final Executor executor = configuration.newExecutor(tx, execType);//2. 创建执行器executor
2.1.3 return new DefaultSqlSession(configuration, executor, autoCommit);//3. 创建SqlSession
获取SqlSession过程
DefaultSqlSessionFactory .java
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
/*
1. 获取 事务
*/
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
// 1. 获取事务
Transaction tx = null;
try {
// environment : app 当前所处的阶段,开发或者测试, 或者发行阶段
final Environment environment = configuration.getEnvironment();
// 1.1 获取事务工厂 ,默认JDBC(JDBC,Spring,Managed(ibatis))
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// 1.2 创建事务
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//1.3 新建执行器 executor
//Executor type: SIMPLE(default), REUSE, BATCH
final Executor executor = configuration.newExecutor(tx, execType);
// 2. 创建 sqlSession
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();
}
}
解释步骤 获取执行器
- Configuration.java
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
// cacheEnabled =true ,默认值不修改的话,一定会走这一步的
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
生成MapperProxy(代理对象)过程:
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
- DefaultSqlSession.java
@Override
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}
- Configuration.java
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
- MapperRegisty.java
@SuppressWarnings("unchecked")
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.java
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
// 返回实例 ,java.lang.reflect 包下的类
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);
}
总结:
- MyBatis 生成实例是通过 Jdk 的proxy 方式生成, 当然也可以采用 cglib 的方式来生成实例对象.
- MyBatis 中Executor 中默认采用委托(装饰器模式, ) CachingExecutor的方式实现
参考:
- https://MyBatis.org/MyBatis-3/zh/
猜你喜欢