继续探究 DruidDataSource 核心类 init 初始化方法
类 DruidDataSource 第 810 行
lock.lockInterruptibly();
复制代码
ReentrantLock 锁有几种:lock、tryLock、tryLock(long timeout, TimeUnit unit)、lockInterruptibly。
这里简单说下 lock 和 lockInterruptibly 的区别
lock 阻塞等待获取锁,优先考虑获取锁,待获取锁成功后,才响应中断。
lockInterruptibly 优先考虑响应中断,而不是响应锁的普通获取或重入获取。
ReentrantLock.lockInterruptibly 允许在等待时由其它线程调用等待线程的 Thread.interrupt 方法来中断等待线程的等待而直接返回,这时不用获取锁,而会抛出一个 InterruptedException。 ReentrantLock.lock 方法不允许 Thread.interrupt 中断,即使检测到 Thread.isInterrupted,一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功后再把当前线程置为 interrupted 状态,然后再中断线程。
接下来
initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());//获取当前线程堆栈跟踪元素数组再转换为String
复制代码
线程类的 getStackTrace() 方法返回一个堆栈跟踪元素数组,表示线程的堆栈转储。数组的第一个元素表示堆栈的顶部,它是序列中的最后一个方法调用。数组的最后一个元素表示堆栈的底部,这是序列中的第一个方法调用。
Utils 是 druid 工具类这里定义另一个 toString 方法将 StackTraceElement[]数组转成字符串,如下:
public static String toString(StackTraceElement[] stackTrace) {
StringBuilder buf = new StringBuilder();
for (StackTraceElement item : stackTrace) {
buf.append(item.toString());
buf.append("\n");
}
return buf.toString();
}
复制代码
this.id = DruidDriver.createDataSourceId();
if (this.id > 1) {
long delta = (this.id - 1) * 100000;
this.connectionIdSeedUpdater.addAndGet(this, delta);
this.statementIdSeedUpdater.addAndGet(this, delta);
this.resultSetIdSeedUpdater.addAndGet(this, delta);
this.transactionIdSeedUpdater.addAndGet(this, delta);
}
复制代码
connectionIdSeedUpdater、statementIdSeedUpdater、resultSetIdSeedUpdater、transactionIdSeedUpdater
这几个都是在抽象类 DruidAbstractDataSource 定义的 AtomicLongFieldUpdater<DruidAbstractDataSource>AtomicLongFieldUpdater 可以对指定"类的 'volatile long'类型的成员"进行原子更新。它是基于反射原理实现的
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
String fieldName) {
Class<?> caller = Reflection.getCallerClass();
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
return new CASUpdater<U>(tclass, fieldName, caller);
else
return new LockedUpdater<U>(tclass, fieldName, caller);
}
复制代码
说明:newUpdater()的作用是获取一个 AtomicIntegerFieldUpdater 类型的对象。它实际上返回的是 CASUpdater 对象,或者 LockedUpdater 对象;具体返回哪一个类取决于 JVM 是否支持 long 类型的 CAS 函数。这里是获取数据库操作相关(connection、statement、resultSet、transction)的种子 ID,并追加了 delta.
if (this.jdbcUrl != null) {
this.jdbcUrl = this.jdbcUrl.trim();
initFromWrapDriverUrl();
}
for (Filter filter : filters) {
filter.init(this);
}
if (this.dbTypeName == null || this.dbTypeName.length() == 0) {
this.dbTypeName = JdbcUtils.getDbType(jdbcUrl, null);
}
DbType dbType = DbType.of(this.dbTypeName);
if (JdbcUtils.isMysqlDbType(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");
}
}
复制代码
这段初始化了 jdbcUrl 并且获取数据库类型名称 DbType 是个枚举类,定义了市场上几乎所有的数据库名其中 JdbcUtils 类会发现这段代码
static {
try {
ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader();
if (ctxClassLoader != null) {
for (Enumeration<URL> e = ctxClassLoader.getResources("META-INF/druid-driver.properties"); e.hasMoreElements();) {
URL url = e.nextElement();
Properties property = new Properties();
InputStream is = null;
try {
is = url.openStream();
property.load(is);
} finally {
JdbcUtils.close(is);
}
DRIVER_URL_MAPPING.putAll(property);
}
}
} catch (Exception e) {
LOG.error("load druid-driver.properties error", e);
}
}
复制代码
可见驱动都在该属性文件中 druid-driver.properties 打开看果然
jdbc:derby:=org.apache.derby.jdbc.EmbeddedDriver
jdbc:mysql:=com.mysql.jdbc.Driver
jdbc:log4jdbc:=net.sf.log4jdbc.DriverSpy
jdbc:oracle:=oracle.jdbc.driver.OracleDriver
jdbc:microsoft:=com.microsoft.jdbc.sqlserver.SQLServerDriver
jdbc:jtds:=net.sourceforge.jtds.jdbc.Driver
jdbc:postgresql:=org.postgresql.Driver
jdbc:fake:=com.alibaba.druid.mock.MockDriver
jdbc:hsqldb:=org.hsqldb.jdbcDriver
jdbc:db2:=COM.ibm.db2.jdbc.app.DB2Driver
jdbc:sqlite:=org.sqlite.JDBC
jdbc:ingres:=com.ingres.jdbc.IngresDriver
jdbc:h2:=org.h2.Driver
jdbc:mckoi:=com.mckoi.JDBCDriver
jdbc:clickhouse:=ru.yandex.clickhouse.ClickHouseDriver
jdbc:highgo:=com.highgo.jdbc.Driver
复制代码
参考:
https://blog.csdn.net/u013308490/article/details/83062433
https://blog.csdn.net/Shujie_L/article/details/123777561
https://blog.csdn.net/wangxiaotongfan/article/details/51798969
评论