【问题标题】:Initialize datasource bean on condition根据条件初始化数据源 bean
【发布时间】:2022-01-25 22:37:50
【问题描述】:

所以,我需要按条件对 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");
    }
}

【问题讨论】:

    标签: spring spring-boot spring-data-jpa


    【解决方案1】:

    我建议您使用@ConditionalOnProperty 注释。它可以用在类或带有@Bean 注解的方法上。我会将两个数据库的配置分开在两个不同的类中(这不是强制性的,您可以使用对 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());
        }
    
    }
    
    

    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);
            }
        }
    
    

    定义了 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
    
    

    【讨论】:

    • 感谢您的回答!有没有办法用 @Condition 注释为 spring-mvc 做同样的事情?
    • 老实说,我不知道。看看这个,也许会有所帮助:ofstack.com/Java/28746/…。您使用 @Condition 而不是 @ConditionalOnProperty 是否有原因?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多