# CLAUDE.md - system-dynamic-datasource

This file provides guidance to Claude Code when working in the system-dynamic-datasource module.

## Purpose

Provides dynamic multi-datasource switching at runtime using Spring's `AbstractRoutingDataSource`. This module has no main class and is not runnable on its own.

## Architecture

```
@DataSource (annotation)
    ↓ triggers
DataSourceAspect (AOP around advice)
    ↓ sets/clears
DynamicContextHolder (ThreadLocal<Deque<String>>)
    ↓ peek() returns key to
DynamicDataSource (extends AbstractRoutingDataSource)
    ↓ routes to
Multiple DataSources (configured in DynamicDataSourceProperties)
```

## Key Classes

### `@DataSource` annotation

Apply to methods or classes to specify which datasource to use. Takes a datasource name string.

### `DataSourceAspect`

AOP aspect that intercepts `@DataSource`-annotated methods. Before invocation, pushes the datasource name onto `DynamicContextHolder`. After invocation (finally block), pops it back off.

### `DynamicContextHolder`

Thread-safe holder using `ThreadLocal<Deque<String>>`. Uses a deque (stack) to support nested `@DataSource` calls -- each method restores the previous datasource on exit.
- `push(String ds)` -- set current datasource
- `poll()` -- restore previous
- `peek()` -- get current (used by DynamicDataSource)

### `DynamicDataSource extends AbstractRoutingDataSource`

`determineCurrentLookupKey()` returns `DynamicContextHolder.peek()`. If the holder is empty, falls back to the default datasource.

### `DynamicDataSourceFactory`

Creates Druid datasource instances from configuration properties.

### Configuration Properties

`DynamicDataSourceProperties`: Maps to YAML `spring.datasource.dynamic.*` with multiple named datasource configs.
`DataSourceProperties`: Individual datasource config (url, username, password, driver-class-name, etc.).

## Usage

```java
@Service
public class SomeService {
    @DataSource("oracle")
    public List<Data> queryFromOracle() {
        // queries run against the "oracle" datasource
    }
}
```

When no `@DataSource` is present, queries use the default (primary) datasource configured in `application-*.yml`.
