MyBatis的运行过程分为两大步:
读取配置文件缓存到Configuration对象中,用于创建SqlSessionFactorySqlSession的执行过程XMLConfigBuilder中解析XML方法源码:
public class XMLConfigBuilder extends BaseBuilder { ...................... 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 { propertiesElement(root.evalNode("properties")); //issue #117 read properties first typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); settingsElement(root.evalNode("settings")); environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631 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); } } ............................ }我们可以看到它是通过一个一个节点的解析XML的内容得到对应的信息,最后构建出一个Configuration对象。 有了Configuration对象,就可以通过SqlSessionFactoryBuilder的build方法构建SqlSessionFactory对象
public class SqlSessionFactoryBuilder { ................... public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); } ....................... }有了SqlSessionFactory对象就可以轻易的获取SqlSession,SqlSession也是个接口,给出了查询、插入、更新、删除的方法。
public class DefaultSqlSessionFactory implements SqlSessionFactory { .................. public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); } .................. }SqlSession中提供了一个getMapper方法,例如:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);源码:
public class DefaultSqlSession implements SqlSession { ............................ public <T> T getMapper(Class<T> type) { return configuration.<T>getMapper(type, this); } ............................ } public class Configuration { ................ public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); } ................. } public class MapperRegistry { private Configuration config; private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>(); public MapperRegistry(Configuration config) { this.config = config; } @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); } } ........................................... }可以很明显的看出,它运用到了Configuration对象的getMapper方法获取对应的接口对象,又运用了映射器的注册器Mapperregistry获取对应的接口对象。首先会判断是否注册一个Mapper,如果没有则抛出异常信息,如果有就会启用MapperProxyFactory工厂生成一个代理实例。
