Mybatis深入之DataSource实例化过程

Mybatis深入之DataSource实例化过程简介

主要介绍Mybatis启动过程中DataSource实例化的过程、为后面解析一个完整SQL执行过程做个前章。

Mybatis中DataSource体系MybatisDataSource整体简介

Mybatis中关于数据库的类都在org.apache.ibatis.datasource包中

Mybatis配置文件中关于数据库的配置:

=======></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中DataSource实例化整体过程

这里以使用Mybatis自带的数据库连接池为例。也就是type为 “POOLED”类型的数据连接。

根据配置文件中type的类型实例化具体的DataSourceFactory。这里是POOLED所以实例化的是PooledDataSourceFactory。通过PooledDataSourceFactory来获取DataSource具体实例:PooledDataSource

对于第一步更详细点的过程:

具体过程

从上一篇中知道Mybatis初始化过程是解析Mybatis配置文件并装配Configuration对象。从Mybatis基础使用中知道Mybatis数据库连接信息的配置是在environments标签中配置的:

=======></environment></environments>

所以想要了解DataSource初始化过程可以从XMLConfigBuilder中的parse方法入手:

(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通过DataSourceFactory获取DataSource

下面首先看如何根据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 #748Class<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);} }这里重点在于TypeAliasRegistry是何时实例化的 上一篇初始化过程中知道Configuration中有一个私有变量protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();进一步看看Configuration实例化的时候其无参构造函数体就知道其缘由 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); }从上面可以看出TypeAliasRegistry在实例化之后并初始化了其内部私有变量private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();来保存一些Type alias(类型别名)供后面程序使用。是我一生的快乐;失去你,是我一生的遗憾;没有你,无法感受心灵的震撼。

Mybatis深入之DataSource实例化过程

相关文章:

你感兴趣的文章:

标签云: