本节,讲解
dataSource.init();
打断点在
stop in com.alibaba.druid.pool.DruidDataSource.init
好,开始研究代码
public void init() throws SQLException {
// 首先确定没有inited
if (inited) {
return;
}
//继续处理
//获取lock
final ReentrantLock lock = this.lock;
try {
//尝试获取lock
lock.lockInterruptibly();
} catch (InterruptedException e) {
throw new SQLException("interrupt", e);
}
//
boolean init = false;
try {
//再次check没有初始化过,有点类似于double check
if (inited) {
return;
}
//
//
//
// main[1] print initStackTrace
// initStackTrace =
// "java.lang.Thread.getStackTrace(Thread.java:1556)
// com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:637)
// com.alibaba.druid.pool.DruidDataSourceFactory.config(DruidDataSourceFactory.java:376)
// com.alibaba.druid.pool.DruidDataSourceFactory.createDataSource(DruidDataSourceFactory.java:154)
// com.alibaba.druid.pool.DruidDataSourceFactory.createDataSource(DruidDataSourceFactory.java:144)
// user.defined.MyDataSourceFactory.getDataSource(MyDataSourceFactory.java:24)
// org.apache.ibatis.builder.xml.XMLConfigBuilder.environmentsElement(XMLConfigBuilder.java:428)
// org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:150)
// org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:111)
// org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:82)
// org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:65)
// test.Test.main(Test.java:23)
// "
initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());
继续执行
//获取本数据源的ID标志
this.id = DruidDriver.createDataSourceId();
if (this.id > 1) {
//同1个JVM里可能有多个数据源,就有多个ID
long delta = (this.id - 1) * 100000;
this.connectionIdSeed.addAndGet(delta);
this.statementIdSeed.addAndGet(delta);
this.resultSetIdSeed.addAndGet(delta);
this.transactionIdSeed.addAndGet(delta);
}
然后处理JDBC
// 处理url
if (this.jdbcUrl != null) {
this.jdbcUrl = this.jdbcUrl.trim();
//进去没做什么事情
initFromWrapDriverUrl();
}
接下来是插件机制,就是初始化了插件
然后是确定dbType
if (this.dbType == null || this.dbType.length() == 0) {
this.dbType = JdbcUtils.getDbType(jdbcUrl, null);
}
这个是根据url的前缀来做的。
======================================================
//构建connectProperties
if (JdbcConstants.MYSQL.equals(this.dbType) || //
JdbcConstants.MARIADB.equals(this.dbType)) {
//
boolean cacheServerConfigurationSet = false;
if (this.connectProperties.containsKey("cacheServerConfiguration")) {
cacheServerConfigurationSet = true;
} else if (this.jdbcUrl.indexOf("cacheServerConfiguration") != -1) {
cacheServerConfigurationSet = true;
}
if (cacheServerConfigurationSet) {
this.connectProperties.put("cacheServerConfiguration", "true");
}
}
//简单的参数check
if (maxActive <= 0) {
throw new IllegalArgumentException("illegal maxActive " + maxActive);
}
if (maxActive < minIdle) {
throw new IllegalArgumentException("illegal maxActive " + maxActive);
}
if (getInitialSize() > maxActive) {
throw new IllegalArgumentException(
"illegal initialSize " + this.initialSize + ", maxActive " + maxActive);
}
if (timeBetweenLogStatsMillis > 0 && useGlobalDataSourceStat) {
throw new IllegalArgumentException(
"timeBetweenLogStatsMillis not support useGlobalDataSourceStat=true");
}
if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
throw new SQLException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
}
// 处理driverClass
if (this.driverClass != null) {
this.driverClass = driverClass.trim();
}
//
//
//
//什么都不做
initFromSPIServiceLoader();
//确定driverClass创建实例
if (this.driver == null) {
if (this.driverClass == null || this.driverClass.isEmpty()) {
this.driverClass = JdbcUtils.getDriverClassName(this.jdbcUrl);
}
if (MockDriver.class.getName().equals(driverClass)) {
driver = MockDriver.instance;
} else {
driver = JdbcUtils.createDriver(driverClassLoader, driverClass);
}
} else {
if (this.driverClass == null) {
this.driverClass = driver.getClass().getName();
}
}
Step completed: "thread=main", com.alibaba.druid.pool.DruidDataSource.init(), line=718 bci=649
718 initCheck();
main[1] step
>
Step completed: "thread=main", com.alibaba.druid.pool.DruidDataSource.initCheck(), line=942 bci=0
942 if (JdbcUtils.ORACLE.equals(this.dbType)) {
main[1] next
>
Step completed: "thread=main", com.alibaba.druid.pool.DruidDataSource.initCheck(), line=955 bci=125
955 } else if (JdbcUtils.DB2.equals(dbType)) {
main[1] next
>
Step completed: "thread=main", com.alibaba.druid.pool.DruidDataSource.initCheck(), line=958 bci=142
958 }
===========接下来,就是initExceptionSorter(); 看看,怎么执行的。
private void initExceptionSorter() {
//从这里开始
if (exceptionSorter instanceof NullExceptionSorter) {
if (driver instanceof MockDriver) {
return;
}
} else if (this.exceptionSorter != null) {
return;
}
String realDriverClassName = driver.getClass().getName();
if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) //
|| realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)) {
//处理这个
this.exceptionSorter = new MySqlExceptionSorter();
---创建ConnectionChecker
private void initValidConnectionChecker() {
//here
//
String realDriverClassName = driver.getClass().getName();
if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) //
|| realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)) {
//针对mysql创建
this.validConnectionChecker = new MySqlValidConnectionChecker();
} else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
|| realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {
this.validConnectionChecker = new OracleValidConnectionChecker();
} else if (realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER)
|| realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4)
|| realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_JTDS)) {
this.validConnectionChecker = new MSSQLValidConnectionChecker();
} else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)) {
this.validConnectionChecker = new PGValidConnectionChecker();
}
}
public MySqlValidConnectionChecker(){
try {
clazz = Utils.loadClass("com.mysql.jdbc.MySQLConnection");
if (clazz == null) {
clazz = Utils.loadClass("com.mysql.cj.jdbc.ConnectionImpl");
}
if (clazz != null) {
ping = clazz.getMethod("pingInternal", boolean.class, int.class);
}
if (ping != null) {
usePingMethod = true;
}
} catch (Exception e) {
LOG.warn("Cannot resolve com.mysql.jdbc.Connection.ping method. Will use 'SELECT 1' instead.", e);
}
configFromProperties(System.getProperties());
}
接着初始化QueryChecker
Step completed: "thread=main", com.alibaba.druid.pool.DruidDataSource.validationQueryCheck(), line=912 bci=4
912 if (!(isTestOnBorrow() || isTestOnReturn() || isTestWhileIdle())) {
main[1] step
>
Step completed: "thread=main", com.alibaba.druid.pool.DruidDataSource.validationQueryCheck(), line=916 bci=22
916 if (this.validConnectionChecker != null) {
main[1] print validConnectionChecker
validConnectionChecker = "com.alibaba.druid.pool.vendor.MySqlValidConnectionChecker@2d1ef81a"
main[1] step
>
Step completed: "thread=main", com.alibaba.druid.pool.DruidDataSource.validationQueryCheck(), line=917 bci=29
917 return;
main[1] step
看来不需要创建了。