MyBatisはDruidを統合して、データベーススレッドプール管理を実現します(2つ)

MyBatisはDruidを統合して、データベーススレッドプール管理を実現します(2つ)

MyBatisとは

MyBatisは、カスタマイズされたSQL、ストアドプロシージャ、および高度なマッピングをサポートする優れた永続化レイヤーフレームワークです。MyBatisは、ほとんどすべてのJDBCコードとパラメーターの手動設定、および結果セットの取得を回避します。MyBatisは、単純なXMLまたは注釈を使用して、ネイティブタイプ、インターフェイス、およびJava POJO(プレーンオールドJavaオブジェクト)をデータベース内のレコードとして構成およびマッピングできます。

MyBatisの主要コンポーネント

  • 構成
  • sqlsession
  • エグゼキュータ

sqlsessionは、構成構成(注釈付きのSQLまたはxml構成ファイル)を解析し、対応するエグゼキューターを使用してデータベース操作を実行し、実行された結果セットを処理して、表示処理のためにアプリケーション層に返します。

詳細については、上記の記事を参照してください

MyBatisの深い理解と使用-MyBatisキャッシュシステム

MyBatisの深い理解と使用-TypeHandler

MyBatisの深い理解と使用-MyBatis

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

公式アカウントの推奨

ここに写真の説明を挿入

おすすめ

転載: blog.csdn.net/shang_xs/article/details/90751859