根据条件初始化数据源 bean
Initialize datasource bean on condition
所以,我需要根据条件来初始化DataSource。我从 .env 文件中获取所有 db-config 数据,其中有一个特殊变量 spring_profiles_active
。当此变量等于“p2”时,我需要初始化 secondDataSource,否则不需要。我该怎么做呢?
我的配置:
@Configuration
public class JpaConfig {
@Value("${jdbc.url}")
private String jdbcUrl;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
@Value("${jdbc.driverClassName}")
private String jdbcDriverClassName;
@Value("${second.jdbc.url}")
private String secondJdbcUrl;
@Value("${second.jdbc.username}")
private String secondJdbcUsername;
@Value("${second.jdbc.password}")
private String secondJdbcPassword;
@Value("${second.jdbc.driverClassName}")
private String secondJdbcDriverClassName;
@Bean
@Primary
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcDriverClassName);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(jdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(jdbcPassword));
return dataSource;
}
@Bean
@Qualifier("secondDataSource")
public DataSource secondDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(secondJdbcDriverClassName);
dataSource.setUrl(secondJdbcUrl);
dataSource.setUsername(secondJdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
return dataSource;
}
@Bean
@Primary
public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dataSource()); }
@Bean
@Qualifier("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) {
return new JdbcTemplate(secondDataSource);
}
}
- 更新:
我尝试使用@Condition 注释来执行此操作,但在
return activeProfile.equals("p2")
中出现异常java.lang.NullPointerException: null。代码:
@Configuration
@Conditional(SecondJpaConfigCondition.class)
public class SecondJpaConfig {
@Value("${second.jdbc.url}")
private String secondJdbcUrl;
@Value("${second.jdbc.username}")
private String secondJdbcUsername;
@Value("${second.jdbc.password}")
private String secondJdbcPassword;
@Value("${second.jdbc.driverClassName}")
private String secondJdbcDriverClassName;
@Bean
@Qualifier("secondDataSource")
public DataSource secondDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(secondJdbcDriverClassName);
dataSource.setUrl(secondJdbcUrl);
dataSource.setUsername(secondJdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
return dataSource;
}
@Bean
@Qualifier("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) {
return new JdbcTemplate(secondDataSource);
}
}
@Component
public class SecondJpaConfigCondition implements Condition {
@Value("${spring.profiles.active}")
private String activeProfile;
@Override
public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
return activeProfile.equals("p2");
}
}
我建议您使用 @ConditionalOnProperty 注释。它可以用在 class 或带有 @Bean 注释的方法上。我将在两个不同的 classes 中分离两个数据库的配置(这不是强制性的,您可以使用 secondDataSource 和 secondJdbcTemplate 方法的注释)并执行如下操作:
JpaConfig(第一个数据源):
@Configuration
public class JpaConfig {
@Value("${jdbc.url}")
private String jdbcUrl;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
@Value("${jdbc.driverClassName}")
private String jdbcDriverClassName;
@Bean
@Primary
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcDriverClassName);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(jdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(jdbcPassword));
return dataSource;
}
@Bean
@Primary
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}
</pre>
JpaConditionalConfig(第二个数据源):
@Configuration
@ConditionalOnProperty(prefix = "cond", name = "spring_profiles_active", havingValue = "p2")
public class JpaOptionalConfig {
@Value("${second.jdbc.url}")
private String secondJdbcUrl;
@Value("${second.jdbc.username}")
private String secondJdbcUsername;
@Value("${second.jdbc.password}")
private String secondJdbcPassword;
@Value("${second.jdbc.driverClassName}")
private String secondJdbcDriverClassName;
@Bean
@Qualifier("secondDataSource")
public DataSource secondDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(secondJdbcDriverClassName);
dataSource.setUrl(secondJdbcUrl);
dataSource.setUsername(secondJdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
return dataSource;
}
@Bean
@Qualifier("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) {
return new JdbcTemplate(secondDataSource);
}
}
</pre>
定义 spring_profiles_active 属性 的属性文件,Spring 将读取该文件以了解是否应创建条件 bean:
jdbc.url=jdbc:h2:mem:mydb
jdbc.username=sa
jdbc.password=password
jdbc.driverClassName=org.h2.Driver
second.jdbc.url=jdbc:h2:mem:mydb
second.jdbc.username=sa
second.jdbc.password=password
second.jdbc.driverClassName=org.h2.Driver
#THIS IS THE PROPERTY USED IN THE CONDITIONAL BEANS
conditional.spring_profiles_active=p2
</pre>
所以,我需要根据条件来初始化DataSource。我从 .env 文件中获取所有 db-config 数据,其中有一个特殊变量 spring_profiles_active
。当此变量等于“p2”时,我需要初始化 secondDataSource,否则不需要。我该怎么做呢?
我的配置:
@Configuration
public class JpaConfig {
@Value("${jdbc.url}")
private String jdbcUrl;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
@Value("${jdbc.driverClassName}")
private String jdbcDriverClassName;
@Value("${second.jdbc.url}")
private String secondJdbcUrl;
@Value("${second.jdbc.username}")
private String secondJdbcUsername;
@Value("${second.jdbc.password}")
private String secondJdbcPassword;
@Value("${second.jdbc.driverClassName}")
private String secondJdbcDriverClassName;
@Bean
@Primary
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcDriverClassName);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(jdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(jdbcPassword));
return dataSource;
}
@Bean
@Qualifier("secondDataSource")
public DataSource secondDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(secondJdbcDriverClassName);
dataSource.setUrl(secondJdbcUrl);
dataSource.setUsername(secondJdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
return dataSource;
}
@Bean
@Primary
public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dataSource()); }
@Bean
@Qualifier("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) {
return new JdbcTemplate(secondDataSource);
}
}
- 更新:
我尝试使用@Condition 注释来执行此操作,但在
return activeProfile.equals("p2")
中出现异常java.lang.NullPointerException: null。代码:
@Configuration
@Conditional(SecondJpaConfigCondition.class)
public class SecondJpaConfig {
@Value("${second.jdbc.url}")
private String secondJdbcUrl;
@Value("${second.jdbc.username}")
private String secondJdbcUsername;
@Value("${second.jdbc.password}")
private String secondJdbcPassword;
@Value("${second.jdbc.driverClassName}")
private String secondJdbcDriverClassName;
@Bean
@Qualifier("secondDataSource")
public DataSource secondDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(secondJdbcDriverClassName);
dataSource.setUrl(secondJdbcUrl);
dataSource.setUsername(secondJdbcUsername);
dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
return dataSource;
}
@Bean
@Qualifier("secondJdbcTemplate")
public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) {
return new JdbcTemplate(secondDataSource);
}
}
@Component
public class SecondJpaConfigCondition implements Condition {
@Value("${spring.profiles.active}")
private String activeProfile;
@Override
public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
return activeProfile.equals("p2");
}
}
我建议您使用 @ConditionalOnProperty 注释。它可以用在 class 或带有 @Bean 注释的方法上。我将在两个不同的 classes 中分离两个数据库的配置(这不是强制性的,您可以使用 secondDataSource 和 secondJdbcTemplate 方法的注释)并执行如下操作:
JpaConfig(第一个数据源):
@Configuration public class JpaConfig { @Value("${jdbc.url}") private String jdbcUrl; @Value("${jdbc.username}") private String jdbcUsername; @Value("${jdbc.password}") private String jdbcPassword; @Value("${jdbc.driverClassName}") private String jdbcDriverClassName; @Bean @Primary public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(jdbcDriverClassName); dataSource.setUrl(jdbcUrl); dataSource.setUsername(jdbcUsername); dataSource.setPassword(EncryptionUtil.decryptProperty(jdbcPassword)); return dataSource; } @Bean @Primary public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dataSource()); } } </pre>
JpaConditionalConfig(第二个数据源):
@Configuration @ConditionalOnProperty(prefix = "cond", name = "spring_profiles_active", havingValue = "p2") public class JpaOptionalConfig { @Value("${second.jdbc.url}") private String secondJdbcUrl; @Value("${second.jdbc.username}") private String secondJdbcUsername; @Value("${second.jdbc.password}") private String secondJdbcPassword; @Value("${second.jdbc.driverClassName}") private String secondJdbcDriverClassName; @Bean @Qualifier("secondDataSource") public DataSource secondDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(secondJdbcDriverClassName); dataSource.setUrl(secondJdbcUrl); dataSource.setUsername(secondJdbcUsername); dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword)); return dataSource; } @Bean @Qualifier("secondJdbcTemplate") public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) { return new JdbcTemplate(secondDataSource); } } </pre>
定义 spring_profiles_active 属性 的属性文件,Spring 将读取该文件以了解是否应创建条件 bean:
jdbc.url=jdbc:h2:mem:mydb jdbc.username=sa jdbc.password=password jdbc.driverClassName=org.h2.Driver second.jdbc.url=jdbc:h2:mem:mydb second.jdbc.username=sa second.jdbc.password=password second.jdbc.driverClassName=org.h2.Driver #THIS IS THE PROPERTY USED IN THE CONDITIONAL BEANS conditional.spring_profiles_active=p2 </pre>