1.获取配置文件的输入流
//1.获取配置文件的输入流
InputStream is= Resources.getResourceAsStream("mybatis-config.xml");
步骤总结:
1.通过Resources 资源工具类(主要作用:把路径下的资源文件读取到流中)中的getResourceAsStream 方法读取资源文件。
2.在读取的过程中 调用 classLoaderWrapper中的getResourceAsStream方法.
3.然后通过对classLoader[]数组的遍历 ,然后进行判断 类加载器中所读的流是否为null;为null返回空;
如果不为null ,则返回InputStream对象。
2.通过SqlSessionFactoryBuilder获取SqlSessionFactory
//2.通过SqlSessionFactoryBuilder获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
查看build()方法
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
//通过输入流构建XMLConfigBuilder对象
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//parser.parse()返回的是Configuration类型对象
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.
}
}
}
查看parser.parse()方法
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
//解析配置文件节点
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
步骤总结:
1.通过SqlSessionFactoryBuilder.build(Reader reader, String environment, Properties properties)方法构建 SqlsessionFactory 实例。
2..通过输入流创建XMLConfigBuilder对象,并使用XMLConfigBuilder.parse()方法(通过Xpath解析的方式去解析mybatis-config.xml 文件 解析的文件内容套接到configuration中)将输入流转换为Configuration对象(这个configuration 相当于 mybatis-config.xml 中的配置文件所对应的类)。
3..利用Configuration对象创建DefaultSqlSessionFactory对象并返回。
3.通过SqlSessionFactory获取SqlSession
SqlSession session = factory.openSession();
openSession 最终调用的是openSessionFromDataSource方法。
有两种方式,第一种是从dataSource,第二种是从Connection连接来创建。
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();
}
}
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
try {
boolean autoCommit;
try {
autoCommit = connection.getAutoCommit();
} catch (SQLException e) {
// Failover to true, as most poor drivers
// or databases won't support transactions
autoCommit = true;
}
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
final Transaction tx = transactionFactory.newTransaction(connection);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
步骤总结:
1.通过configuration对象获取Environment对象。
2.通过Environment对象(环境)去获取事务工厂对象。
3.通过事务工厂获取事务。
4.通过dataSource的配置获取事务的对象
5.根据事务执行器的类型创建执行器Executor(相当于Statement)通过执行器。
6.通过执行器,事务自动提交以及配置文件对象,创建DefaultSqlSession对象并返回。
4.获取Mapper
UserMapper mapper = session.getMapper(UserMapper.class);
调用SqlSession的getMapper方法获取,其调用的Configuration类的getMapper()方法,这里的type为需要获取的mapper接口。
DefaultSqlSession.class
@Override
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
Configuration类的getMapper()方法,其调用的是mapperRegistry类的getMapper方法,参数是接口和当前的sqlSession。
Configuration.class
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
MapperRegistry类的getMapper方法,这里先获取一个MapperProxyFactory对象,并通过MapperProxyFactory的newInstance来创建Mapper对象。
MapperRegistry.class
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类的newInstance方法
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
步骤总结:
1.第一层通过调用sqlsession中getMapper方法
2.第二层通过调用配置中的getMapper方法
3.第三层通过映射的注册器中的getMapper方法来进行获取相应的Mapper对象
4.先获取一个MapperProxyFactory对象,并通过MapperProxyFactory的newInstance来创建Mapper对象。
(使用了反射和动态代理的方式来获取最终的mapper对象,newInstance创建了mapper接口的动态代理对象,而被代理的方法被放到MapperProxy类中,因此获取Mapper对象就是一个创建其动态代理的过程。)