• MyBatis源码解析(七)——DataSource数据源模块之托管数据源


    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6675700.html 

    1 回顾

      之前介绍的非池型与池型数据源都是MyBatis自己定义的内部使用的数据源,在我们单独使用MyBatis框架架构系统的时候会使用到,但是这种情况不多见,因为MyBatis最常见的使用方式是与Spring进行整合使用,这时我们在项目中一般不会使用MyBatis内置的池型数据源,而是使用外部的C3P0或者DBCP之类的第三方数据源jar包,在整合第三方数据源的时候,我们就需要使用到MyBatis中专门提供的一个数据源工厂----JndiDataSourceFactory。

    2 JNDI数据源

      JNDI数据源只提供了一个JNDI数据源工厂:JndiDataSourceFactory,这个数据源的作用与事务模块中MANAGED类型的事务一致,也属于托管型,它用于在使用诸如与Spring容器整合的场合,在这种场合下,我们一般不会使用MyBatis提供的池型连接来进行数据库访问,而是使用较为专业的dbcp或c3p0来完成数据库访问,这时为了便于使这些外部定义的数据源整合到MyBatis的环境中,就需要使用这个JNDI数据源工厂来进行获取,这就是与外部数据源对接的接口。

      也可以这么理解,这里只定义了数据源工厂,真正的数据源由外部来提供,这还是纯种的抽象工厂模式。

      而MyBatis现在最流行的用法就是与Spring进行整合,所有这个类是使用最为频繁的,但是所有的是在均在源码中进行,对用户是完全透明的。这里我们单单解析这个数据源工厂,至于整合之后的情况以后讨论。

     1 package org.apache.ibatis.datasource.jndi;
     2 import java.util.Map.Entry;
     3 import java.util.Properties;
     4 import javax.naming.Context;
     5 import javax.naming.InitialContext;
     6 import javax.naming.NamingException;
     7 import javax.sql.DataSource;
     8 import org.apache.ibatis.datasource.DataSourceException;
     9 import org.apache.ibatis.datasource.DataSourceFactory;
    10 /**
    11  * JNDI数据源工厂
    12  * 这个数据源的实现是为了使用如 Spring 或应用服务器这类的容器, 容器可以集 中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
    13  */
    14 public class JndiDataSourceFactory implements DataSourceFactory {
    15 
    16   public static final String INITIAL_CONTEXT = "initial_context";
    17   public static final String DATA_SOURCE = "data_source";
    18   //和其他数据源配置相似, 它也可以通过名为 “env.” 的前缀直接向初始上下文发送属性。 比如:
    19   //env.encoding=UTF8
    20   public static final String ENV_PREFIX = "env.";
    21 
    22   private DataSource dataSource;
    23 
    24   @Override
    25   public void setProperties(Properties properties) {
    26     try {
    27       InitialContext initCtx = null;
    28       Properties env = getEnvProperties(properties);
    29       if (env == null) {
    30         initCtx = new InitialContext();
    31       } else {
    32         initCtx = new InitialContext(env);
    33       }
    34 
    35       if (properties.containsKey(INITIAL_CONTEXT)
    36           && properties.containsKey(DATA_SOURCE)) {
    37         Context ctx = (Context) initCtx.lookup(properties.getProperty(INITIAL_CONTEXT));
    38         dataSource = (DataSource) ctx.lookup(properties.getProperty(DATA_SOURCE));
    39       } else if (properties.containsKey(DATA_SOURCE)) {
    40         dataSource = (DataSource) initCtx.lookup(properties.getProperty(DATA_SOURCE));
    41       }
    42 
    43     } catch (NamingException e) {
    44       throw new DataSourceException("There was an error configuring JndiDataSourceTransactionPool. Cause: " + e, e);
    45     }
    46   }
    47 
    48   @Override
    49   public DataSource getDataSource() {
    50     return dataSource;
    51   }
    52 
    53   private static Properties getEnvProperties(Properties allProps) {
    54     final String PREFIX = ENV_PREFIX;
    55     Properties contextProperties = null;
    56     for (Entry<Object, Object> entry : allProps.entrySet()) {
    57       String key = (String) entry.getKey();
    58       String value = (String) entry.getValue();
    59       //和其他数据源配置相似, 它也可以通过名为 “env.” 的前缀直接向初始上下文发送属性。 比如:
    60       //env.encoding=UTF8
    61       if (key.startsWith(PREFIX)) {
    62         if (contextProperties == null) {
    63           contextProperties = new Properties();
    64         }
    65         contextProperties.put(key.substring(PREFIX.length()), value);
    66       }
    67     }
    68     return contextProperties;
    69   }
    70 
    71 }

      在这个工厂类中,很简单的定义了一个继承自DataSourceFactory的获取数据源的方法getDataSource()方法,用于获取外部创建的数据源实例。

      再然后就是同样继承自DataSourceFactory的设置属性的方法,与非池型数据源工厂中类似,JNDI型数据源也可以通过前缀的方式设置一些数据源的属性来传递到数据源中,用来设置数据源的基本信息,所有有设置属性一方法存在。

      在这个工厂中定义了一个上下文概念,JNDI数据源就是通过在外部数据源上覆盖一个上下文,即将数据源添加到某个上下文中,将这个上下文传递到工厂,由工厂从上下文中获取这个数据源,并通过getDataSource()被获取。

      研究够了这个就可以明白如何进行针对MyBatis来整合的程序的开发。只要针对这个工厂来开发就行。

      至此,有关数据源的解析就结束了,数据源模块与之前解析的事务模块为组装Environment环境的两个重要的唯二的模块,而Environment又是构建Configuration配置类的首要模块。

      之后我们要接着解析Configuration构建所需的其他模块内容。

      (未完待续哦!)

  • 相关阅读:
    Hadoop及HIVE学习宝典收集
    【iOS知识学习】_int、NSInteger、NSUInteger、NSNumber的差别和联系
    mysql 连接慢的问题
    CF704D Captain America
    常用流
    流的概念及基本分类
    是否可从一个static方法内发出对非static方法的调用?
    hashCode方法的作用?
    ClassLoader如何加载class?
    class.forName的作用?
  • 原文地址:https://www.cnblogs.com/V1haoge/p/6675700.html
Copyright © 2020-2023  润新知