복붙노트

[SPRING] 관리되지 않는 @Bean에 @ConfigurationProperties 사용

SPRING

관리되지 않는 @Bean에 @ConfigurationProperties 사용

Bean을 내 컨텍스트에 노출시키지 않고도 @ConfigurationProperties 환상적인 기능을 활용하고 싶습니다. @Primaries 등의 문제는 아니기 때문에 다른 데이터 소스를 컨텍스트에 노출 할 수 없습니다. 어떻게하면 다음을 달성 할 수 있습니까?

@ConfigurationProperties("com.non.exposed.datasource.hikari")
public DataSource privateHikariDatasource() {
    if (Objects.isNull(this.nonExposedDatasource)) {
        this.nonExposedDatasource = this.nonExposedDatasourceProperties.initializeDataSourceBuilder().build();
    }
    return this.nonExposedDatasource;
}

@ LppEdd의 답변 덕분에, 완벽한 완벽한 해결책은 다음과 같습니다.

@Autowired
private Environment environment;

public DataSource privateHikariDatasource() {
    if (Objects.isNull(this.nonExposedDatasource)) {
        this.nonExposedDatasource = bindHikariProperties(this.nonExposedDatasourceProperties.initializeDataSourceBuilder().build());
    }
    return this.nonExposedDatasource;
}

//This does exactly the same as @ConfigurationProperties("com.non.exposed.hikari") but without requiring the exposure of the Datasource in the ctx as @Bean
private <T extends DataSource> T bindHikariProperties(final T instance) {
    return Binder.get(this.environment).bind("com.non.exposed.datasource.hikari", Bindable.ofInstance(instance)).get();
}

그럼 당신은 당신의 bean을 this.private HikariDatasource ()로 내부적으로 호출하여 다른 빈에서 사용할 수 있습니다. @ LppEdd에 큰 감사를드립니다!

해결법

  1. ==============================

    1.이 DataSource가 클래스에 비공개이고, 클래스를 포함하는 것이 Spring 컨텍스트 내에 있거나 존재할 수 있으므로 @ConfigurationProperties 클래스를 가질 수 있습니다

    이 DataSource가 클래스에 비공개이고, 클래스를 포함하는 것이 Spring 컨텍스트 내에 있거나 존재할 수 있으므로 @ConfigurationProperties 클래스를 가질 수 있습니다

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

    @EnableConfigurationProperties를 통해 등록하면 자동 와이어 링에 사용할 수 있습니다.

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

    따라서 포함하는 클래스에서 자동으로 실행될 수 있습니다.

    @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는 수동으로 DataSource 인스턴스를 생성합니다. DataSource를 빌드 할 때 동기화를 처리해야한다는 점을 기억하십시오.

    최종 응답은 DataSourceProperties를 다시 사용할 수 없다는 것입니다. 속성의 접두어를 변경하기 위해 그것을 확장 할 수도 없습니다. 컨텍스트 안에는 인스턴스가 하나만 존재할 수 있습니다. 당신이 할 수있는 최선은 봄이하는 일을 모방하는 것입니다.

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

    새로운 @ConfigurationProperties 클래스를 정의 할 수 있습니다.

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

    그런 다음 @ Configuration / @ Component 클래스에서이 속성 클래스를 자동으로 호출합니다. 인 코드 주석을 따르십시오.

    @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;
        }
    }
    
  2. from https://stackoverflow.com/questions/55248571/use-configurationproperties-over-non-managed-bean by cc-by-sa and MIT license