Use @ConfigurationProperties over non-managed @Bean

前端 未结 1 970
悲哀的现实
悲哀的现实 2021-01-15 08:43

I would like to benefit from @ConfigurationProperties fantastic facilities without needing to expose the bean into my context. It is not a problem of @Pri

相关标签:
1条回答
  • 2021-01-15 09:12

    Being that this DataSource is private to a class, and that containing class can be/is inside the Spring context, you can have a @ConfigurationProperties class

    @ConfigurationProperties("com.foo.bar.datasource.hikari")
    public class HikariConfiguration { ... }
    

    Which, by registering it via @EnableConfigurationProperties, is available for autowiring

    @EnableConfigurationProperties(HikariConfiguration.class)
    @SpringBootApplication
    public class Application { ... }
    

    And thus can be autowired in the containing class

    @Component
    class MyClass {
       private final HikariConfiguration hikariConfiguration;  
       private DataSource springDatasource;
    
       MyClass(final HikariConfiguration hikariConfiguration) {
          this.hikariConfiguration = hikariConfiguration;
       }
    
       ...
    
       private DataSource privateSingletonDataSource() {
          if (Objects.isNull(this.springDatasource)) {
             this.springDatasource = buildDataSource(this.hikariConfiguration);
          }
    
          return this.springDatasource;
       }
    }
    

    buildDataSource will manually construct the DataSource instance.
    Remember that you need to take care of synchronization when building the DataSource.


    Final response is that you cannot re-use DataSourceProperties. You can't even extend it to change the properties' prefix. Only a single instance of it can exist inside the context.
    The best you can do is mimic what Spring does.

    Having

    com.non.exposed.datasource.hikari.url=testUrl
    com.non.exposed.datasource.hikari.username=testUsername
    com.non.exposed.datasource.hikari.password=testPassword
    ...
    

    You can define a new @ConfigurationProperties class

    @ConfigurationProperties("com.non.exposed.datasource")
    public class NonExposedProperties {
        private final Map<String, String> hikari = new HashMap<>(8);
    
        public Map<String, String> getHikari() {
            return hikari;
        }
    }
    

    Then, autowire this properties class in your @Configuration/@Component class.
    Follow in-code comments.

    @Configuration
    public class CustomConfiguration {
        private final NonExposedProperties nonExposedProperties;
        private DataSource dataSource;
    
        CustomConfiguration(final NonExposedProperties nonExposedProperties) {
            this.nonExposedProperties= nonExposedProperties;
        }
    
        public DataSource dataSource() {
            if (Objects.isNull(dataSource)) {
                // Create a standalone instance of DataSourceProperties
                final DataSourceProperties dataSourceProperties = new DataSourceProperties();
    
                // Use the NonExposedProperties "hikari" Map as properties' source. It will be
                // {
                //    url      -> testUrl
                //    username -> testUsername
                //    password -> testPassword
                //    ... other properties
                // }
                final ConfigurationPropertySource source = new MapConfigurationPropertySource(nonExposedProperties.getHikari());
    
                // Bind those properties to the DataSourceProperties instance
                final BindResult<DataSourceProperties> binded =
                        new Binder(source).bind(
                                ConfigurationPropertyName.EMPTY,
                                Bindable.ofInstance(dataSourceProperties)
                        );
    
                // Retrieve the binded instance (it's not a new one, it's the same as before)
                dataSource = binded.get().initializeDataSourceBuilder().build();
            }
    
            // Return the constructed HikariDataSource
            return dataSource;
        }
    }
    
    0 讨论(0)
提交回复
热议问题