記事ディレクトリ
AOP+ アノテーション方式は複数のデータソースの原理を実現します
ThreadLocal のスレッド分離を通じて、スレッドをデータ ソース ID にバインドします。
- 設定されていない場合は、デフォルトのデータソースが使用されます。
- 設定されている場合、データ ソース ID に対応するデータ ソースを使用します (注: データ ソース ID は使用後にクリアする必要があります)
考えられる問題
シナリオ 1: 指定されたデータ ソースのリクエストでエラーが発生しました
問題の説明: 指定されたデータ ソースのリクエストでエラーが発生しましたが、データ ソースを指定しなかった後続のリクエストでは、指定されたデータ ソースが使用されました (デフォルトのデータ ソースを使用する必要があります)。
コード:
@Slf4j
@Aspect
@Order(-2)
@Component
public class DataSourceAspect {
@Pointcut("@annotation(com.joker.datasource.aopannotation.DataSource) || @within(com.joker.datasource.aopannotation.DataSource)")
public void run(){
}
@Around("run()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
// 方法上获取
// AnnotatedElementUtils.hasAnnotation()
DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
if (Objects.isNull(dataSource)) {
// 类上获取
dataSource = AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
}
// 设置数据源
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
Object obj = point.proceed();
// 清除数据源
DynamicDataSourceContextHolder.clearDataSourceType();
return obj;
}
}
問題分析:
- 指定されたデータ ソースのリクエストでエラーが発生したため、データ ソース ID のクリアが実行されず、現在のスレッド thread1 がまだデータ ソースにバインドされています。
- インターフェースリクエストで使用されるスレッドはスレッドプールで管理されるため、後続のスレッドthread1は引き続き他のリクエストに割り当てられる可能性があります。
- 後続のリクエストでスレッド thread1 が使用され、データ ソースが指定されていない場合、以前にバインドされたデータ ソースが引き続き使用され、間違ったデータ ソースが使用されます (本来はデフォルトのデータ ソースが使用されるはずです)。
- ただし、後続のリクエストでスレッド thread1 が使用され、データ ソースが指定されている場合は、問題はありません。
シナリオ 2: 指定されたデータ ソースのリクエストで新しいスレッドを使用する
問題の説明: 指定されたデータ ソースのリクエストで新しいスレッドが使用されるため、指定されたデータ ソースが無効になり、デフォルトのデータ ソースが使用されます。
問題分析: データ ソースはスレッドにバインドされているため、現在のスレッドが指定されたデータ ソースにバインドされている場合でも、リクエストで新しいスレッドが使用されている場合、新しいスレッドはデータ ソースにバインドされません (デフォルトのデータ ソースがデフォルトで使用されます)。新しいスレッドを使用する次のシナリオ:
- new Thread() によって作成された新しいスレッドが使用され、データ ソースは新しいスレッドで使用されます。
- スレッド プールは、スレッド プール内のスレッドを通じてデータ ソースを使用するために使用されます。
- Java8のlist.ParallelStream()を利用して並列処理(マルチスレッド処理)を行い、処理中にデータを利用する