MyBatisはDruidを統合して、データベーススレッドプール管理を実現します(2つ)
MyBatisとは
MyBatisは、カスタマイズされたSQL、ストアドプロシージャ、および高度なマッピングをサポートする優れた永続化レイヤーフレームワークです。MyBatisは、ほとんどすべてのJDBCコードとパラメーターの手動設定、および結果セットの取得を回避します。MyBatisは、単純なXMLまたは注釈を使用して、ネイティブタイプ、インターフェイス、およびJava POJO(プレーンオールドJavaオブジェクト)をデータベース内のレコードとして構成およびマッピングできます。
MyBatisの主要コンポーネント
- 構成
- sqlsession
- エグゼキュータ
sqlsessionは、構成構成(注釈付きのSQLまたはxml構成ファイル)を解析し、対応するエグゼキューターを使用してデータベース操作を実行し、実行された結果セットを処理して、表示処理のためにアプリケーション層に返します。
詳細については、上記の記事を参照してください
Druidとは何ですか?
Druidは、Java言語で最高のデータベース接続プールです。Druidは、強力な監視と拡張機能を提供できます。
詳細については、上記の記事を参照してください。
その他の関連知識については、前の記事を参照してください。MyBatisはDruidを統合してデータベーススレッドプール管理を実現します(1)
自動組み立てプロセス
spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
DataSourceAutoConfiguration自動アセンブリ実現
@Configuration
@ConditionalOnClass({
DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({
DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceInitializationConfiguration.class })// 初始化DataSource信息
public class DataSourceAutoConfiguration {
@Configuration
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({
DataSource.class, XADataSource.class })
@Import({
DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
DataSourceJmxConfiguration.class })
protected static class PooledDataSourceConfiguration {
}
}
Druidが使用されているため、新しい構成が追加され、構成ソースは前の記事にあります。
/**
* @ClassName: DataSource
* @Description: DataSource 数据源配置类,可选择 DruidDataSource、UnpooledDataSource、PooledDataSource
* @Author: 尚先生
* @CreateDate: 2019/5/22 12:44
* @Version: 1.0
*/
@Configuration
public class DataSourceConfiguration {
@Value("${spring.druid.filters}")
private String filters;
// 采用 Druid 实现线程池
@Bean
@ConfigurationProperties(prefix = "spring.druid")
public DataSource dataSource() throws SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setFilters(filters);
return druidDataSource;
}
}
DruidDataSourceコード分析
public class DruidDataSource extends DruidAbstractDataSource implements DruidDataSourceMBean, ManagedDataSource, Referenceable, Closeable, Cloneable, ConnectionPoolDataSource, MBeanRegistration {
public DruidDataSource(boolean fairLock){
// 默认采用非公平锁机制
super(fairLock);
// 配置数据源属性信息
configFromPropety(System.getProperties());
}
}
TransactionAutoConfiguration自動アセンブリ実現
@Configuration
@ConditionalOnClass(PlatformTransactionManager.class)
@AutoConfigureAfter({
JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
// 数据库事务的实现
DataSourceTransactionManagerAutoConfiguration.class,
Neo4jDataAutoConfiguration.class })
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {
}
クエリ処理を開始します
AbstractPlatformTransactionManager#getTransaction
DataSourceTransactionManager#doGetTransaction
DataSourceTransactionManager#doBegin
DruidDataSource#getConnection
DruidDataSource#init
new DruidPooledConnection(holder)がタイムアウトした場合、指定された時間内に接続を取得します
private DruidPooledConnection getConnectionInternal(long maxWait) throws SQLException {
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
connectErrorCount.incrementAndGet();
throw new SQLException("interrupt", e);
}
try {
if (maxWait > 0) {
holder = pollLast(nanos);
} else {
holder = takeLast();
}
} catch (InterruptedException e) {
connectErrorCount.incrementAndGet();
throw new SQLException(e.getMessage(), e);
} catch (SQLException e) {
connectErrorCount.incrementAndGet();
throw e;
} finally {
lock.unlock();
}
holder.incrementUseCount();
DruidPooledConnection poolalbeConnection = new DruidPooledConnection(holder);
return poolalbeConnection;
}
DruidDataSourceを初期化します
public void init() throws SQLException {
if (inited) {
return;
}
// Lock 实现锁机制
final ReentrantLock lock = this.lock;
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
throw new SQLException("interrupt", e);
}
// 保证值初始化一次
boolean init = false;
try {
if (inited) {
return;
}
// 设置 reset 开关
dataSourceStat.setResetStatEnable(this.resetStatEnable);
// DruidDataSource保存DruidConnectionHolder的数组,保存所有的数据库连接
// DruidConnectionHolder持有数据库连接,还有所在的DataSource等
// DruidPooledConnection持有DruidConnectionHolder,所在线程等
connections = new DruidConnectionHolder[maxActive];
evictConnections = new DruidConnectionHolder[maxActive];
keepAliveConnections = new DruidConnectionHolder[maxActive];
SQLException connectError = null;
boolean asyncInit = this.asyncInit && createScheduler == null;
if (!asyncInit) {
try {
// 初始化 connection
for (int i = 0, size = getInitialSize(); i < size; ++i) {
PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
connections[poolingCount] = holder;
incrementPoolingCount();
}
createAndLogThread();
createAndStartCreatorThread();
createAndStartDestroyThread();
initedLatch.await();
init = true;
if (keepAlive) {
// 异步进行最小任务数处理
if (createScheduler != null) {
for (int i = 0; i < minIdle; ++i) {
createTaskCount++;
CreateConnectionTask task = new CreateConnectionTask();
this.createSchedulerFuture = createScheduler.submit(task);
}
} else {
this.emptySignal();
}
}
finally {
// 标记初始化完成
inited = true;
// 释放锁
lock.unlock();
}
}
タイムアウト後の接続取得
// 使用Lock-Condition
DruidConnectionHolder takeLast() throws InterruptedException, SQLException {
try {
while (poolingCount == 0) {
emptySignal(); // 发出信号去创建连接
notEmptyWaitThreadCount++;
if (notEmptyWaitThreadCount > notEmptyWaitThreadPeak) {
notEmptyWaitThreadPeak = notEmptyWaitThreadCount;
}
try {
notEmpty.await(); //发出信号去复用或者创建连接
} finally {
notEmptyWaitThreadCount--;
}
notEmptyWaitCount++;
if (!enable) {
connectErrorCount.incrementAndGet();
throw new DataSourceDisableException();
}
}
} catch (InterruptedException ie) {
notEmpty.signal(); // 传播 non-interrupted 线程
notEmptySignalCount++;
throw ie;
}
decrementPoolingCount();
DruidConnectionHolder last = connections[poolingCount];
connections[poolingCount] = null;
return last;
}
DruidPooledConnection#close
public void close() throws SQLException {
// 如果为 true 表示已经关闭
if (this.disable) {
return;
}
if (filters.size() > 0) {
FilterChainImpl filterChain = new FilterChainImpl(dataSource);
filterChain.dataSource_recycle(this);
} else {
// 回收连接处理
recycle();
}
this.disable = true;
}
1. DruidDataSourceは、DruidConnectionHolderの配列を保持し、すべてのデータベース接続を保存します
private volatile DruidConnectionHolder[] connections; // 注意这里的volatile
2. DruidConnectionHolderは、データベース接続、およびそれが配置されているDataSourceなどを保持します。
private final DruidAbstractDataSource dataSource;
private final Connection conn;
// 成员变量,可以做缓存,也可以做统计
private PreparedStatementPool statementPool;
private final List<Statement> statementTrace = new ArrayList<Statement>(2);
3. DruidPooledConnectionは、DruidConnectionHolder、それが配置されているスレッドなどを保持します。
protected volatile DruidConnectionHolder holder;
private final Thread ownerThread;
総括する
この共有には、主にトランザクション管理PlatformTransactionManagerとDruidDataSourceのアセンブリとソースコード分析、トランザクション制御の範囲内でのsqlsession接続の合理的な使用、DruidDataSourceを使用してDruidConnectionHolderを配列の形式で保存し、DruidConnectionHolderを使用して保持されているデータベース接続と関連するデータソースDataSourceを保存します。上記の組み合わせ関係により、DruidPooledConnectionを使用して現在のスレッド情報やDruidConnectionHolder配列などを保存し、接続数の動的制御とsqlSession共有の問題を実現し、Druidの運用・保守層の接続をタイムリー・統計・動的に監視する機能を実現できます。
より優れた記事
javaの小学生
https://blog.csdn.net/shang_xs
MyBatis関連の詳細
MyBatisの詳細な理解と使用-MyBatisキャッシュシステム
https://blog.csdn.net/shang_xs/article/details/86656353MyBatisの
詳細な理解と使用-MyBatisキャッシュシステム
https://blog.csdn.net/shang_xs/article/details / 86656353MyBatisの
深い理解と使用-TypeHandlerhttps : //blog.csdn.net/shang_xs/article/details/86656173
SpringはTomcatとJndiを組み合わせて、データソースの外部構成を実現します
https://blog.csdn.net/shang_xs/article/details/90599810
Springは、JbossとJndiを組み合わせて、データソースの外部構成を実装します
https://blog.csdn.net/shang_xs/article/details/90610242
サーブレットの詳細な研究と理解(1)
https://blog.csdn.net/shang_xs/article/details/90371068のIn
サーブレットの深さ研究と理解(2)
https://blog.csdn.net/shang_xs/article/details/90376489
完全なコードと関連する依存関係については、GitHubを参照してください。
https://github.com/dwyanewede/spring-boot/tree/master/spring-webmvc/src/main