Druid监控功能
- druid提供了丰富的监控功能,这篇文章主要分析下监控功能的实现原理。
- 通过代理模式控制statement对象的访问。druid里的Statement、PreparedStatement、Connection等对象都通过代理模式访问。对应的druid的代理是StatementProxyImpl、PreparedStatementProxyImpl、ConnectionProxyImpl。
- 通过filter过滤器链增加监控和日志功能。
Connection
- Druid的连接对象PhysicalConnectionInfo的创建过程经过FilterChainImpl进行封装,核心是经过相关的Filter进行包装。
public abstract class DruidAbstractDataSource extends WrapperAdapter implements DruidAbstractDataSourceMBean, DataSource, DataSourceProxy, Serializable {
public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {
String url = this.getUrl();
Properties connectProperties = getConnectProperties();
// 省略相关的代码
try {
// 创建物理链接
conn = createPhysicalConnection(url, physicalConnectProperties);
connectedNanos = System.nanoTime();
} catch (SQLException ex) {
throw ex;
} catch (RuntimeException ex) {
throw ex;
} catch (Error ex) {
throw ex;
} finally {
long nano = System.nanoTime() - connectStartNanos;
createTimespan += nano;
creatingCountUpdater.decrementAndGet(this);
}
// 创建PhysicalConnectionInfo
return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos, variables, globalVariables);
}
public Connection createPhysicalConnection(String url, Properties info) throws SQLException {
Connection conn;
if (getProxyFilters().size() == 0) {
conn = getDriver().connect(url, info);
} else {
// 通过FilterChainImpl进行装饰
conn = new FilterChainImpl(this).connection_connect(info);
}
createCountUpdater.incrementAndGet(this);
return conn;
}
- FilterChainImpl返回Connection对象,通过PhysicalConnectionInfo封装。
public class FilterChainImpl implements FilterChain {
public ConnectionProxy connection_connect(Properties info) throws SQLException {
// 通过Filter进行封装
if (this.pos < filterSize) {
return nextFilter()
.connection_connect(this, info);
}
Driver driver = dataSource.getRawDriver();
String url = dataSource.getRawJdbcUrl();
Connection nativeConnection = driver.connect(url, info);
if (nativeConnection == null) {
return null;
}
return new ConnectionProxyImpl(dataSource, nativeConnection, info, dataSource.createConnectionId());
}
}
- FilterChainImpl内部经过Filter进行封装,核心是通过Filter进行封装。
- 在经过Filter封装前创建的时ConnectionProxyImpl对象,外层进行Filter的包装。
- Connection的封装对象是ConnectionProxyImpl对象。
Statement
- Druid的连接对象PreparedStatement的创建过程经过FilterChainImpl进行封装,核心是经过相关的Filter进行包装。
- Druid的连接对象Statement的创建过程经过FilterChainImpl进行封装,核心是经过相关的Filter进行包装。
public class ConnectionProxyImpl extends WrapperProxyImpl implements ConnectionProxy {
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
FilterChainImpl chain = createChain();
// 通过FilterChainImpl获取prepareStatement
PreparedStatement stmt = chain.connection_prepareStatement(this, sql);
recycleFilterChain(chain);
return stmt;
}
}
public class FilterChainImpl implements FilterChain {
@Override
public PreparedStatementProxy connection_prepareStatement(
ConnectionProxy connection,
String sql,
int autoGeneratedKeys) throws SQLException
{
// 通过FilterChainImpl获取prepareStatement
if (this.pos < filterSize) {
return nextFilter()
.connection_prepareStatement(this, connection, sql, autoGeneratedKeys);
}
PreparedStatement statement = connection.getRawObject().prepareStatement(sql, autoGeneratedKeys);
if (statement == null) {
return null;
}
// 返回 PreparedStatementProxyImpl
return new PreparedStatementProxyImpl(connection, statement, sql, dataSource.createStatementId());
}
}
- FilterChainImpl内部经过Filter进行封装,核心是通过Filter进行封装。
- 在经过Filter封装前创建的时PreparedStatementProxyImpl对象,外层进行Filter的包装。
- PreparedStatement的代理对象是PreparedStatementProxyImpl。
Filter
- Filter的所有相关接口在FilterAdapter都有默认实现,其他的具体的实现通过继承FilterAdapter后进行重写。