druid数据源根据url自动加载相应驱动的原理
# 数据源配置 spring: datasource: type: com.alibaba.druid.pool.DruidDataSource #driverClassName: com.mysql.cj.jdbc.Driver druid: # 主库数据源 master: url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8 username: root password: root
上述为一个常见的springboot使用druid作为数据源的配置,可以看到driverClassName的配置是可以注释掉的,那druid是如何知道该加载哪一种数据库驱动呢,下面一起分析一下。在DataSource的getConnection调用时必须知道加载的驱动是什么,才能拿到相关的Connection,于是从这一步开始分析:
1配置的数据源DruidDataSource:
@Override public DruidPooledConnection getConnection() throws SQLException { return getConnection(maxWait); }
2下一步:
public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException { init(); if (filters.size() > 0) { FilterChainImpl filterChain = new FilterChainImpl(this); return filterChain.dataSource_connect(this, maxWaitMillis); } else { return getConnectionDirect(maxWaitMillis); } }
3下一步进入inint方法:
public void init() throws SQLException { if (inited) { ...... if (this.driver == null) { if (this.driverClass == null || this.driverClass.isEmpty()) { this.driverClass = JdbcUtils.getDriverClassName(this.jdbcUrl); }........ } } }
4下一步进入JdbcUtils.getDriverClassName方法:
public static String getDriverClassName(String rawUrl) throws SQLException { if (rawUrl == null) { return null; } if (rawUrl.startsWith("jdbc:derby:")) { return "org.apache.derby.jdbc.EmbeddedDriver"; } else if (rawUrl.startsWith("jdbc:mysql:")) { if (mysql_driver_version_6 == null) { mysql_driver_version_6 = Utils.loadClass("com.mysql.cj.jdbc.Driver") != null; } if (mysql_driver_version_6) { return MYSQL_DRIVER_6; } else { return MYSQL_DRIVER; } } else if (rawUrl.startsWith("jdbc:log4jdbc:")) { return LOG4JDBC_DRIVER; } else if (rawUrl.startsWith("jdbc:mariadb:")) { return MARIADB_DRIVER; } else if (rawUrl.startsWith("jdbc:oracle:") // || rawUrl.startsWith("JDBC:oracle:")) { return ORACLE_DRIVER; } else if (rawUrl.startsWith("jdbc:alibaba:oracle:")) { return ALI_ORACLE_DRIVER; } else if (rawUrl.startsWith("jdbc:microsoft:")) { return "com.microsoft.jdbc.sqlserver.SQLServerDriver"; } else if (rawUrl.startsWith("jdbc:sqlserver:")) { return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; } else if (rawUrl.startsWith("jdbc:sybase:Tds:")) { return "com.sybase.jdbc2.jdbc.SybDriver"; } else if (rawUrl.startsWith("jdbc:jtds:")) { return "net.sourceforge.jtds.jdbc.Driver"; } else if (rawUrl.startsWith("jdbc:fake:") || rawUrl.startsWith("jdbc:mock:")) { return "com.alibaba.druid.mock.MockDriver"; } else if (rawUrl.startsWith("jdbc:postgresql:")) { return POSTGRESQL_DRIVER; } else if (rawUrl.startsWith("jdbc:edb:")) { return ENTERPRISEDB_DRIVER; } else if (rawUrl.startsWith("jdbc:odps:")) { return ODPS_DRIVER; } else if (rawUrl.startsWith("jdbc:hsqldb:")) { return "org.hsqldb.jdbcDriver"; } else if (rawUrl.startsWith("jdbc:db2:")) { return DB2_DRIVER; } else if (rawUrl.startsWith("jdbc:sqlite:")) { return SQLITE_DRIVER; } else if (rawUrl.startsWith("jdbc:ingres:")) { return "com.ingres.jdbc.IngresDriver"; } else if (rawUrl.startsWith("jdbc:h2:")) { return H2_DRIVER; } else if (rawUrl.startsWith("jdbc:mckoi:")) { return "com.mckoi.JDBCDriver"; } else if (rawUrl.startsWith("jdbc:cloudscape:")) { return "COM.cloudscape.core.JDBCDriver"; } else if (rawUrl.startsWith("jdbc:informix-sqli:")) { return "com.informix.jdbc.IfxDriver"; } else if (rawUrl.startsWith("jdbc:timesten:")) { return "com.timesten.jdbc.TimesTenDriver"; } else if (rawUrl.startsWith("jdbc:as400:")) { return "com.ibm.as400.access.AS400JDBCDriver"; } else if (rawUrl.startsWith("jdbc:sapdb:")) { return "com.sap.dbtech.jdbc.DriverSapDB"; } else if (rawUrl.startsWith("jdbc:JSQLConnect:")) { return "com.jnetdirect.jsql.JSQLDriver"; } else if (rawUrl.startsWith("jdbc:JTurbo:")) { return "com.newatlanta.jturbo.driver.Driver"; } else if (rawUrl.startsWith("jdbc:firebirdsql:")) { return "org.firebirdsql.jdbc.FBDriver"; } else if (rawUrl.startsWith("jdbc:interbase:")) { return "interbase.interclient.Driver"; } else if (rawUrl.startsWith("jdbc:pointbase:")) { return "com.pointbase.jdbc.jdbcUniversalDriver"; } else if (rawUrl.startsWith("jdbc:edbc:")) { return "ca.edbc.jdbc.EdbcDriver"; } else if (rawUrl.startsWith("jdbc:mimer:multi1:")) { return "com.mimer.jdbc.Driver"; } else if (rawUrl.startsWith("jdbc:dm:")) { return JdbcConstants.DM_DRIVER; } else if (rawUrl.startsWith("jdbc:kingbase:")) { return JdbcConstants.KINGBASE_DRIVER; } else if (rawUrl.startsWith("jdbc:gbase:")) { return JdbcConstants.GBASE_DRIVER; } else if (rawUrl.startsWith("jdbc:xugu:")) { return JdbcConstants.XUGU_DRIVER; } else if (rawUrl.startsWith("jdbc:hive:")) { return JdbcConstants.HIVE_DRIVER; } else if (rawUrl.startsWith("jdbc:hive2:")) { return JdbcConstants.HIVE_DRIVER; } else if (rawUrl.startsWith("jdbc:phoenix:thin:")) { return "org.apache.phoenix.queryserver.client.Driver"; } else if (rawUrl.startsWith("jdbc:phoenix://")) { return JdbcConstants.PHOENIX_DRIVER; } else if (rawUrl.startsWith("jdbc:kylin:")) { return JdbcConstants.KYLIN_DRIVER; } else if (rawUrl.startsWith("jdbc:elastic:")) { return JdbcConstants.ELASTIC_SEARCH_DRIVER; } else if (rawUrl.startsWith("jdbc:clickhouse:")) { return JdbcConstants.CLICKHOUSE_DRIVER; } else if(rawUrl.startsWith("jdbc:presto:")) { return JdbcConstants.PRESTO_DRIVER; }else { throw new SQLException("unkow jdbc driver : " + rawUrl); } }
从这个方法可以看到druid是根据我们配置的url信息进行查找返回类名字符串,比如我们配置的为:
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8
那根据jdbc:mysql即返回mysql的驱动类名,后续再通过反射进行加载使用。
druid官网说明:Druid是根据url前缀来识别DriverClass的,这样使得配置更方便简洁。
前缀 | DriverCLass | 描述信息 |
jdbc:odps | com.aliyun.odps.jdbc.OdpsDriver | |
jdbc:derby | org.apache.derby.jdbc.EmbeddedDriver | |
jdbc:mysql | com.mysql.jdbc.Driver | |
jdbc:oracle | oracle.jdbc.driver.OracleDriver | |
jdbc:microsoft | com.microsoft.jdbc.sqlserver.SQLServerDriver | |
jdbc:sybase:Tds | com.sybase.jdbc2.jdbc.SybDriver | |
jdbc:jtds | net.sourceforge.jtds.jdbc.Driver | |
jdbc:postgresql | org.postgresql.Driver | |
jdbc:fake | com.alibaba.druid.mock.MockDriver | |
jdbc:mock | com.alibaba.druid.mock.MockDriver | |
jdbc:hsqldb | org.hsqldb.jdbcDriver | |
jdbc:db2 | COM.ibm.db2.jdbc.app.DB2Driver | DB2的JDBC Driver十分混乱,这个匹配不一定对 |
jdbc:sqlite | org.sqlite.JDBC | |
jdbc:ingres | com.ingres.jdbc.IngresDriver | |
jdbc:h2 | org.h2.Driver | |
jdbc:mckoi | com.mckoi.JDBCDriver | |
jdbc:cloudscape | COM.cloudscape.core.JDBCDriver | |
jdbc:informix-sqli | com.informix.jdbc.IfxDriver | |
jdbc:timesten | com.timesten.jdbc.TimesTenDriver | |
jdbc:as400 | com.ibm.as400.access.AS400JDBCDriver | |
jdbc:sapdb | com.sap.dbtech.jdbc.DriverSapDB | |
jdbc:JSQLConnect | com.jnetdirect.jsql.JSQLDriver | |
jdbc:JTurbo | com.newatlanta.jturbo.driver.Driver | |
jdbc:firebirdsql | org.firebirdsql.jdbc.FBDriver | |
jdbc:interbase | interbase.interclient.Driver | |
jdbc:pointbase | com.pointbase.jdbc.jdbcUniversalDriver | |
jdbc:edbc | ca.edbc.jdbc.EdbcDriver | |
jdbc:mimer:multi1 | com.mimer.jdbc.Driver |