Druid源码分析(三)-- 初始化DataSource2
Druid源码分析(三)-- 初始化DataSource2
init
昨天分析了init 函数的双重校验+锁,今天接着往下看源码
initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());
this.id = DruidDriver.createDataSourceId();
这里用的是原子类Integer,来保证自增是线程安全的
private final static AtomicInteger dataSourceIdSeed = new AtomicInteger(0);
public static int createDataSourceId() {
return dataSourceIdSeed.incrementAndGet();
}
多数据源处理
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);
}
接下来是加载filters,自带的监控filter等在这里加载
for (Filter filter : filters) {
filter.init(this);
}
public void init(DataSourceProxy dataSource) {
lock.lock();
try {
if (this.dbType == null) {
this.dbType = DbType.of(dataSource.getDbType());
}
configFromProperties(dataSource.getConnectProperties());
configFromProperties(System.getProperties());
} finally {
lock.unlock();
}
}
接着往下看,是校验dbTypeName ,没配置的话会调用JdbcUtils 的函数通过jdbcUrl来获取
if (this.dbTypeName == null || this.dbTypeName.length() == 0) {
this.dbTypeName = JdbcUtils.getDbType(jdbcUrl, null);
}
public static DbType getDbTypeRaw(String rawUrl, String driverClassName) {
...
if (rawUrl.startsWith("jdbc:mysql:") || rawUrl.startsWith("jdbc:cobar:")
|| rawUrl.startsWith("jdbc:log4jdbc:mysql:")) {
return DbType.mysql;
} else if (rawUrl.startsWith("jdbc:mariadb:")) {
return DbType.mariadb;
} else if (rawUrl.startsWith("jdbc:oracle:") || rawUrl.startsWith("jdbc:log4jdbc:oracle:")) {
return DbType.oracle;
...
}
下面就是校验一些参数的合法性
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);
}
SPI机制
自定义的filter在这里加载
private void initFromSPIServiceLoader() {
if (loadSpifilterSkip) {
return;
}
if (autoFilters == null) {
List<Filter> filters = new ArrayList<Filter>();
ServiceLoader<Filter> autoFilterLoader = ServiceLoader.load(Filter.class);
for (Filter filter : autoFilterLoader) {
AutoLoad autoLoad = filter.getClass().getAnnotation(AutoLoad.class);
if (autoLoad != null && autoLoad.value()) {
filters.add(filter);
}
}
autoFilters = filters;
}
for (Filter filter : autoFilters) {
...
addFilter(filter);
}
}
总结
我发现开源项目大多都有SPI机制来支持用户自定义filter ,平常工作中项目的扩展性也可以考虑使用这个机制
|