在 Spring Boot 中获取对当前活动数据源的引用

Posted

技术标签:

【中文标题】在 Spring Boot 中获取对当前活动数据源的引用【英文标题】:Get a reference to currently active dataSource in Spring Boot 【发布时间】:2017-08-25 20:16:33 【问题描述】:

我想通过DataSourceInitializer实现db数据初始化。

我在我的 Spring Boot 主方法下面有这些方法,但它似乎根本没有被执行(我尝试故意删除字符只是为了触发一个可以确认执行的错误。什么也没发生。 ):

@ConfigurationProperties(prefix="spring.datasource")
@Bean
public DataSource getDataSource() 

    // i was hoping this was going to pull my current datasource, as 
    // defined in application.properties
    return DataSourceBuilder
            .create()
            .build();



@Bean
public DataSourceInitializer dataSourceInitializer() 
    ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
    resourceDatabasePopulator.addScript(new ClassPathResource("/data/init/initData.sql"));

    DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();

    // the call to the above method
    dataSourceInitializer.setDataSource(getDataSource());


    dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);

    return dataSourceInitializer;

更新:这个问题旨在获取对正在使用的数据源的引用。这个问题解释了如何以非常简单的方式初始化数据: DataSourceInitializer is not working on Spring boot 1.2

【问题讨论】:

【参考方案1】:

如果你已经创建了一个数据源,它将在 spring 容器中,所以:

@Autowired
DataSource dataSource;

应该这样做。

【讨论】:

做了更改,但数据库中仍然没有更改。你知道我的代码还有什么问题吗? Java 魔法!谢谢你。就我而言,我有多种可能的自动装配选择,因此必须指定一个更细粒度的数据源类,如下所示:@Autowired private HikariDataSource dataSource; 如果你有不同的数据源怎么办? @itro 您可以自动装配 Spring 容器中的任何接口或类,如果存在唯一匹配,则会找到它。【参考方案2】:

您是说您的应用程序主方法下方有这些方法,并且您没有自动装配数据源,因此您直接创建了一个实例,因此不使用属性。您需要使用 Spring 创建的单例对象。为此,您有两种可能:

第一个选项,也是您应该使用的选项,是声明一个配置类来创建您的 bean:

@Configuration
public class DatasourceConfig


    @ConfigurationProperties(prefix="spring.datasource")
    @Bean
    public DataSource getDataSource() 

        // i was hoping this was going to pull my current datasource, as 
        // defined in application.properties
        return DataSourceBuilder
                .create()
                .build();
    

    @Bean
    public DataSourceInitializer dataSourceInitializer() 
        ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
        resourceDatabasePopulator.addScript(new ClassPathResource("/data/init/initData.sql"));

        DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();

        // the call to the above method
        dataSourceInitializer.setDataSource(getDataSource());


        dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);

        return dataSourceInitializer;
    


使用@Configuration,甚至直接调用该方法,因为配置类在启动时使用CGLIB进行子类化,您将获得Spring创建的对象。

Further information about how Java-based configuration works internally

第二个选项是在第二种方法中自动连接数据源:

@Bean
@Autowired
public DataSourceInitializer dataSourceInitializer(DataSource myDatasource) 
    ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
    resourceDatabasePopulator.addScript(new ClassPathResource("/data/init/initData.sql"));

    DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();

    dataSourceInitializer.setDataSource(myDatasource);
    dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);

    return dataSourceInitializer;

【讨论】:

查看我的问题末尾的更新。它以这种方式工作,但可以肯定的是,它非常神奇,我的目标是学习如何摆脱 Boot 的自动配置。现在,我尝试将@Autowireding DataSource 作为一个字段,并按照您的建议将其放在@Bean 下方。两种方法都行不通。 @developer10 使用属性初始化你的 bean 是否正常?是否正在创建 DataSourceInitializer?如果没有,请您展示您的主要方法吗? 我的主要方法是标准SpringBoot的方法,只是标准行。我不知道如何检查您的要求 - 我没有看到任何表明它不是的错误。但是,我怀疑它根本没有被调用。那可能吗?注意:此时我对默认行为很好——Spring Boot 提取并执行我放置在资源根目录中的data.sql 文件(因为它不需要其他任何东西——我只是暂时注释掉了有问题的方法)。 只需在您的@Bean 方法中记录一些内容。还要检查,在启动您的应用程序时,bean 不会被覆盖。寻找类似Overriding bean definition for bean 'dataSourceInitializer'

以上是关于在 Spring Boot 中获取对当前活动数据源的引用的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring Boot 以编程方式确定当前的活动配置文件 [重复]

如何使用 Spring Boot 以编程方式确定当前的活动配置文件 [重复]

如何使用 Spring Boot 以编程方式确定当前的活动配置文件 [重复]

查看当前 Spring (Boot) 属性

如何使用 Keycloak 在 Spring Boot 中获取当前登录用户?

如何使用 Spring Boot 从 SQL Server 获取当前数据库时间