package com.xiaoleilu.hutool.db.ds; import javax.sql.DataSource; import com.xiaoleilu.hutool.db.ds.c3p0.C3p0DSFactory; import com.xiaoleilu.hutool.db.ds.dbcp.DbcpDSFactory; import com.xiaoleilu.hutool.db.ds.druid.DruidDSFactory; import com.xiaoleilu.hutool.db.ds.hikari.HikariDSFactory; import com.xiaoleilu.hutool.db.ds.pooled.PooledDSFactory; import com.xiaoleilu.hutool.db.ds.tomcat.TomcatDSFactory; import com.xiaoleilu.hutool.log.Log; import com.xiaoleilu.hutool.log.LogFactory; import com.xiaoleilu.hutool.setting.Setting; import com.xiaoleilu.hutool.util.StrUtil; /** * 数据源工厂类 * * @author Looly * */ public abstract class DSFactory { private static final Log log = LogFactory.get(); protected static final String DEFAULT_DB_SETTING_PATH = "config/db.setting"; /** 数据源名 */ private String dataSourceName; /** 数据库连接配置文件 */ protected Setting setting; /** * 构造 * @param dataSourceName 数据源名称 * @param setting 数据库连接配置 */ public DSFactory(String dataSourceName, Setting setting) { this.dataSourceName = dataSourceName; if(null == setting){ setting = new Setting(DEFAULT_DB_SETTING_PATH, true); } this.setting = setting; } /** * 获得默认数据源 * * @return 数据源 */ public DataSource getDataSource(){ return getDataSource(StrUtil.EMPTY); } /** * 获得分组对应数据源 * * @param group 分组名 * @return 数据源 */ public abstract DataSource getDataSource(String group); /** * 关闭默认数据源(空组) */ public void close(){ close(StrUtil.EMPTY); } /** * 关闭对应数据源 * @param group */ public abstract void close(String group); /** * 销毁工厂类,关闭所有数据源 */ public abstract void destroy(); /** * 检查连接池(Connection Pool)实现是否存在<br> * 此方法仅用于检查所提供的DataSource类是否存在,当传入的DataSource类不存在时抛出ClassNotFoundException<br> * 此方法的作用是在detectDSFactory方法自动检测所用连接池时,如果实现类不存在,调用此方法会自动抛出异常,从而切换到下一种连接池的检测。 * * @param dsClass DataSource子类 */ protected void checkCPExist(Class<? extends DataSource> dsClass) { //Do nothing only use datasource class for check exist or not. } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((dataSourceName == null) ? 0 : dataSourceName.hashCode()); result = prime * result + ((setting == null) ? 0 : setting.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null){ return false; } if (getClass() != obj.getClass()) { return false; } DSFactory other = (DSFactory) obj; if (dataSourceName == null) { if (other.dataSourceName != null) { return false; } } else if (!dataSourceName.equals(other.dataSourceName)) { return false; } if (setting == null) { if (other.setting != null) { return false; } } else if (!setting.equals(other.setting)) { return false; } return true; } //------------------------------------------------------------------------- Static start //JVM关闭是关闭所有连接池 static{ Runtime.getRuntime().addShutdownHook(new Thread(){ @Override public void run() { if(null != currentDSFactory){ currentDSFactory.destroy(); log.debug("DataSource: [{}] destroyed.", currentDSFactory.dataSourceName); } } }); } private static DSFactory currentDSFactory; private static final Object lock = new Object(); /** * 获得数据源<br> * 使用默认配置文件的无分组配置 * * @return 数据源 */ public static DataSource get(){ return get(null); } /** * 获得数据源 * * @param group 配置文件中对应的分组 * @return 数据源 */ public static DataSource get(String group){ return get(null, group); } /** * 获得数据源 * * @param dbSetting 数据库配置文件,如果为<code>null</code>,查找默认的配置文件 * @param group 配置文件中对应的分组 * @return 数据源 */ public static DataSource get(Setting dbSetting, String group){ return getCurrentDSFactory(dbSetting).getDataSource(group); } /** * @param setting 数据源配置文件 * @return 当前使用的数据源工厂 */ public static DSFactory getCurrentDSFactory(Setting setting){ if(null == currentDSFactory){ synchronized (lock) { if(null == currentDSFactory){ currentDSFactory = detectDSFactory(setting); } } } return currentDSFactory; } /** * @param dsFactory 数据源工厂 * @return 自定义的数据源工厂 */ synchronized public static DSFactory setCurrentDSFactory(DSFactory dsFactory){ if(null != currentDSFactory){ if(currentDSFactory.equals(dsFactory)){ return currentDSFactory;//数据源不变时返回原数据源 } //自定义数据源工厂前关闭之前的数据源 currentDSFactory.destroy(); } log.debug("Custom use [{}] datasource.", dsFactory.dataSourceName); currentDSFactory = dsFactory; return currentDSFactory; } /** * 决定数据源实现工厂<br> * 连接池优先级:Hikari > Druid > Tomcat > Dbcp > C3p0 > Hutool Pooled * @return 日志实现类 */ private static DSFactory detectDSFactory(Setting setting){ DSFactory dsFactory; try { dsFactory = new HikariDSFactory(setting); } catch (NoClassDefFoundError e1) { try { dsFactory = new DruidDSFactory(setting); } catch (NoClassDefFoundError e2) { try { dsFactory = new TomcatDSFactory(setting); } catch (NoClassDefFoundError e3) { try { dsFactory = new DbcpDSFactory(setting); } catch (NoClassDefFoundError e4) { try { dsFactory = new C3p0DSFactory(setting); } catch (NoClassDefFoundError e5) { //默认使用Hutool实现的简易连接池 dsFactory = new PooledDSFactory(setting); } } } } } log.debug("Use [{}] DataSource As Default", dsFactory.dataSourceName); return dsFactory; } //------------------------------------------------------------------------- Static end }