Spring Dynamic DataSource Routing

Spring Dynamic DataSource Routing(AbstractRoutingDataSource)

AbstractRoutingDataSource.java 클래스에 abstract 메소드로 determineCurrentLookupKey 존재한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {

@Override
public Connection getConnection() throws SQLException {
return determineTargetDataSource().getConnection();
}

@Override
public Connection getConnection(String username, String password) throws SQLException {
return determineTargetDataSource().getConnection(username, password);
}

protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
}
@Nullable
protected abstract Object determineCurrentLookupKey();
}

대충 코드를 보면 위와같은 내용인데 getConnection 할때 determineCurrentLookupKey를 통해 resolvedDataSources 데이터에 있는 connection을 찾아서 해당 커넥션을 넘기는 방법이다.

그럼 간단한 예제를 보면 이해하기 쉬울것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public enum RoutingDataSourceLookupKey{
READ,WRITE
}

public class ReplicationRoutingDataSource extends AbstractRoutingDataSource {

@Override
protected Object determineCurrentLookupKey() {
return TransactionSynchronizationManager.isCurrentTransactionReadOnly() ? RoutingDataSourceLookupKey.READ : RoutingDataSourceLookupKey.WRITE;
}
}

@Configuration
public class DataSourceConfigration{
@Bean
public DataSource routingDataSource(DataSource writeDataSource, DataSource readDataSource) {

var routingDataSource = new ReplicationRoutingDataSource();
var dataSourceMap = new HashMap<>();
dataSourceMap.put(RoutingDataSourceLookupKey.WRITE, writeDataSource);
dataSourceMap.put(RoutingDataSourceLookupKey.READ, readDataSource);
routingDataSource.setTargetDataSources(dataSourceMap);
routingDataSource.setDefaultTargetDataSource(readDataSource);

return routingDataSource;
}
}

위와같은 방법으로도 처리를 할수있다.

참고자료