主要介绍Mybatis启动过程中DataSource实例化的过程、为后面解析一个完整SQL执行过程做个前章。
Mybatis中关于数据库的类都在org.apache.ibatis.datasource包中 
Mybatis配置文件中关于数据库的配置:
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
<dataSource type="POOLED">的type属性、其有三种取值: 类与类之间的关系: 
 
每一条线都是一种关系、简单解释一下 
 1. PooledDataSource实现java.sql.DataSource接口 
 2. PooledDataSource内部持有一个DataSource引用 
 3. UnpooledDataSource实现java.sql.DataSource接口 
 4. PooledDataSource内部持有一个UnpooledDataSource引用 
 5.PooledDataSourceFactory无参构造方法体中将其父类UnpooledDataSourceFactory持有的引用DataSource实例化为PooledDataSource 
 6. PooledDataSourceFactory继承UnpooledDataSourceFactory 
 7. UnpooledDataSourceFactory无参构造方法将其持有的引用DataSource实例化为UnpooledDataSource 
 8. UnpooledDataSourceFactory持有一个DataSource引用、用于返回实例化好的DataSource。
这里以使用Mybatis自带的数据库连接池为例。也就是type为 “POOLED”类型的数据连接。
对于第一步更详细点的过程:
private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();中、也包括TypeAliasRegistry无参构造方法注册的基本java类型。从上一篇中知道Mybatis初始化过程是解析Mybatis配置文件并装配Configuration对象。从Mybatis基础使用中知道Mybatis数据库连接信息的配置是在environments标签中配置的:
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>所以想要了解DataSource初始化过程可以从XMLConfigBuilder中的parse方法入手:
  private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        if (isSpecifiedEnvironment(id)) {
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          DataSource dataSource = dsFactory.getDataSource();
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dataSource);
          configuration.setEnvironment(environmentBuilder.build());
        }
      }
    }
  }主要看如何实例化DataSource、同样从上面代码中我们知道只是将DataSource实例化了而没有进行任何操作、原因是只有具体执行某SQL语句的时候才会使用DataSource来获取数据库连接。
获取DataSource关键代码:
DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          DataSource dataSource = dsFactory.getDataSource();下面首先看如何根据dataSource标签内容实例化DataSourceFactory
  private DataSourceFactory dataSourceElement(XNode context) throws Exception {
    if (context != null) {
      //获取数据库连接池类型: POOLED-使用Mybatis自带数据库连接池。UNPOOL-不使用数据库连接池。这里看POOLED的情况。
      String type = context.getStringAttribute("type");
      Properties props = context.getChildrenAsProperties();
      DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance();
      factory.setProperties(props);
      return factory;
    }
    throw new BuilderException("Environment declaration requires a DataSourceFactory.");
  }resolveClass(type)TypeAliasRegistry  @SuppressWarnings("unchecked")
  // throws class cast exception as well if types cannot be assigned
  public <T> Class<T> resolveAlias(String string) {
    try {
      if (string == null) return null;
      String key = string.toLowerCase(Locale.ENGLISH); // issue #748
      Class<T> value;
      if (TYPE_ALIASES.containsKey(key)) {
        value = (Class<T>) TYPE_ALIASES.get(key);
      } else {
        value = (Class<T>) Resources.classForName(string);
      }
      return value;
    } catch (ClassNotFoundException e) {
      throw new TypeException("Could not resolve type alias ‘" + string + "‘.  Cause: " + e, e);
    }
  }protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();  public Configuration() {
    typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
    typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
    typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
    typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
    typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
    typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
    typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
    typeAliasRegistry.registerAlias("LRU", LruCache.class);
    typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
    typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
    typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
    typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
    typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
    typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
    typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
    typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
    typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
    typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
    typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
    typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
    typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
    typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
    languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
    languageRegistry.register(RawLanguageDriver.class);
  }private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();来保存一些Type alias(类型别名)供后面程序使用。从上面代码typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);可以看出最后返回的是PooledDataSourceFactory。
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
  public PooledDataSourceFactory() {
    this.dataSource = new PooledDataSource();
  }
}其中UnpooledDataSourceFactory拥有一个DataSource的protected级别的属性protected DataSource dataSource;并且其构造函数:
  public UnpooledDataSourceFactory() {
    this.dataSource = new UnpooledDataSource();
  }
对比PooledDataSourceFactory的构造函数:
  public PooledDataSourceFactory() {
    this.dataSource = new PooledDataSource();
  }知道最终UnpooledDataSourceFactory的protected DataSource dataSource;实例是:PooledDataSource。
到这里只要知道PooledDataSource是什么、那么返回的DataSource就是什么。 
当然在这之前还需要一步、就是将配置文件中的数据库连接信息设置到最后生成的DataSourceFactory(在这里就是PooledDataSourceFactory)中去。这个过程中使用了一个Mybatis很长用的用于操作反射的封装类:MetaObject。提供了一些简便的获取、设置类等通过反射来操作类的方法、以后有时间专门看一眼。
下面的主要目标就是看PooledDataSource调用其无参构造方法时到底做了什么。
PooledDataSource是java.sql.DataSource的一个实现类、其属性与无参构造方法如下:
  private static final Log log = LogFactory.getLog(PooledDataSource.class);
  private final PoolState state = new PoolState(this);
  private final UnpooledDataSource dataSource;
  // OPTIONAL CONFIGURATION FIELDS
  protected int poolMaximumActiveConnections = 10;
  protected int poolMaximumIdleConnections = 5;
  protected int poolMaximumCheckoutTime = 20000;
  protected int poolTimeToWait = 20000;
  protected String poolPingQuery = "NO PING QUERY SET";
  protected boolean poolPingEnabled = false;
  protected int poolPingConnectionsNotUsedFor = 0;
  private int expectedConnectionTypeCode;
  public PooledDataSource() {
    dataSource = new UnpooledDataSource();
  }dataSource = new UnpooledDataSource();到这里、关于数据库DataSource类的实例话也就结束了。
当使用数据库连接池时、即<dataSource type="POOLED">时、DataSourceFactory具体实例是PooledDataSourceFactory。返回的DataSource具体实例是内部持有UnpooledDataSource实例的PooledDataSource。
当不使用数据库连接池时、即<dataSource type="UNPOOLED">  时、DataSourceFactory具体实例是UnpooledDataSourceFactory。返回的DataSource具体实例是UnpooledDataSource实例。
更多内容:Mybatis 目录
原文:http://blog.csdn.net/crave_shy/article/details/46584803