ConfigurationProperties配置动态数据源
时间: 2025-04-22 08:29:57 浏览: 29
<think>好的,用户现在想了解如何在Spring Boot中使用@ConfigurationProperties来配置动态数据源,并且需要示例。我之前已经回答过关于Maven配置阿里云仓库的问题,现在需要结合用户提供的站内引用内容来回答这个问题。
首先,我需要回顾用户提供的引用内容。引用[1]、[2]、[3]都提到了动态数据源的配置,其中引用[2]提到需要排除DataSourceAutoConfiguration,引用[1]和[3]提到了使用AbstractRoutingDataSource。引用[4]虽然讲的是Redis多数据源,但配置方式可能有类似之处,比如使用配置文件定义多个数据源属性。
用户的问题明确提到了使用@ConfigurationProperties,所以需要将动态数据源的配置与这个注解结合起来。通常,@ConfigurationProperties用于将配置文件中的属性绑定到Java对象上,这样可以在代码中方便地使用这些配置。
接下来,我需要考虑动态数据源的一般步骤:定义多个数据源的配置,创建数据源实例,设置动态数据源路由,以及配置Spring Boot应用。结合@ConfigurationProperties,可以为每个数据源创建一个配置类,绑定对应的前缀,然后在动态数据源配置中加载这些配置。
用户可能的需求是希望通过配置文件(如application.yml)来定义多个数据源,然后在代码中动态切换。需要确保排除自动配置的数据源,避免冲突,这点在引用[2]中提到过。因此,在启动类上需要排除DataSourceAutoConfiguration。
然后,需要定义数据源配置类,使用@ConfigurationProperties绑定前缀,比如spring.datasource.master和spring.datasource.slave。接着,创建AbstractRoutingDataSource的子类,实现determineCurrentLookupKey方法,根据当前线程选择数据源标识。
在配置类中,需要将多个数据源注入,并设置到AbstractRoutingDataSource中。同时,需要配置事务管理和SqlSessionFactory,确保动态切换生效。
用户可能还需要示例代码,所以需要提供YAML配置示例、数据源属性类、动态路由类、配置类以及使用方式,比如通过注解或手动切换数据源。
需要验证用户是否理解如何排除自动配置,如何绑定多个数据源的属性,以及如何在实际业务中使用动态切换。可能的问题包括配置是否正确、事务管理是否影响数据源切换等,这些需要在注意事项中提及。
最后,生成的相关问题需要围绕动态数据源的配置和使用,比如如何结合MyBatis、事务处理、性能优化等,帮助用户深入理解。</think>### 使用 `@ConfigurationProperties` 配置动态数据源的完整示例
#### 一、核心配置步骤
1. **排除自动配置**
在 Spring Boot 启动类中禁用默认数据源自动配置,避免与动态数据源冲突:
```java
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application { ... }
```
参考自多数据源配置的通用做法[^2]。
2. **定义数据源配置类**
使用 `@ConfigurationProperties` 绑定多个数据源配置(YAML 格式):
```yaml
# application.yml
datasource:
master:
url: jdbc:mysql://localhost:3306/master_db
username: root
password: master_pwd
driver-class-name: com.mysql.cj.jdbc.Driver
slave:
url: jdbc:mysql://localhost:3306/slave_db
username: root
password: slave_pwd
driver-class-name: com.mysql.cj.jdbc.Driver
```
3. **创建数据源属性绑定类**
```java
@Getter
@Setter
@ConfigurationProperties(prefix = "datasource")
public class DataSourceProperties {
private DataSourceConfig master;
private DataSourceConfig slave;
@Data
public static class DataSourceConfig {
private String url;
private String username;
private String password;
private String driverClassName;
}
}
```
4. **动态数据源路由实现**
继承 `AbstractRoutingDataSource` 实现动态切换逻辑:
```java
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
@Override
protected Object determineCurrentLookupKey() {
return CONTEXT_HOLDER.get();
}
public static void setDataSourceKey(String key) {
CONTEXT_HOLDER.set(key);
}
public static void clearDataSourceKey() {
CONTEXT_HOLDER.remove();
}
}
```
5. **数据源配置类**
装配动态数据源并注入多数据源配置:
```java
@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceConfig {
@Bean
@Primary
public DataSource dynamicDataSource(DataSourceProperties properties) {
Map<Object, Object> targetDataSources = new HashMap<>();
// 创建主数据源
DataSource master = DataSourceBuilder.create()
.url(properties.getMaster().getUrl())
.username(properties.getMaster().getUsername())
.password(properties.getMaster().getPassword())
.driverClassName(properties.getMaster().getDriverClassName())
.build();
// 创建从数据源
DataSource slave = DataSourceBuilder.create()
.url(properties.getSlave().getUrl())
.username(properties.getSlave().getUsername())
.password(properties.getSlave().getPassword())
.driverClassName(properties.getSlave().getDriverClassName())
.build();
targetDataSources.put("master", master);
targetDataSources.put("slave", slave);
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(master); // 默认主库
return dynamicDataSource;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dynamicDataSource) {
return new DataSourceTransactionManager(dynamicDataSource);
}
}
```
---
#### 二、使用动态数据源
1. **通过注解切换数据源**
自定义 `@DataSource` 注解实现声明式切换:
```java
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value() default "master";
}
@Aspect
@Component
public class DataSourceAspect {
@Before("@annotation(dataSource)")
public void beforeSwitch(JoinPoint joinPoint, DataSource dataSource) {
DynamicDataSource.setDataSourceKey(dataSource.value());
}
@After("@annotation(dataSource)")
public void afterSwitch(DataSource dataSource) {
DynamicDataSource.clearDataSourceKey();
}
}
```
2. **业务层调用示例**
```java
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@DataSource("master")
public User getMasterUser(Long id) {
return userMapper.selectById(id);
}
@DataSource("slave")
public User getSlaveUser(Long id) {
return userMapper.selectById(id);
}
}
```
---
#### 三、关键注意事项
1. **事务管理**
在事务方法中切换数据源可能失效,建议在事务边界外切换数据源或使用 `ChainedTransactionManager`[^3]。
2. **连接池配置**
可在 `DataSourceConfig` 中添加连接池参数(如 HikariCP):
```yaml
datasource:
master:
hikari:
maximum-pool-size: 10
connection-timeout: 30000
```
3. **多数据源 MyBatis 集成**
需为每个数据源单独配置 `SqlSessionFactory`(参考多数据源 MyBatis 配置[^2])。
---
#### 四、验证配置
1. 启动应用时观察日志中是否加载了多个数据源配置
2. 通过 `DEBUG` 模式跟踪 `DynamicDataSource.determineCurrentLookupKey()` 方法
3. 执行单元测试验证不同数据源操作结果
---
#### 相关问题
1. 动态数据源切换如何与 Spring 事务管理器协同工作?
2. 如何为不同的 MyBatis Mapper 接口指定不同数据源?
3. 动态数据源配置下如何实现读写分离自动化?
阅读全文
相关推荐


















