代码之家  ›  专栏  ›  技术社区  ›  coderatchet

Spring引导使用新前缀扩展现有属性类

  •  2
  • coderatchet  · 技术社区  · 7 年前

    我想设置一些自定义数据源属性( "app.datasource.alternate" )除了标准 DataSourceProperties ( "spring.datasource" )。

    这两个数据源没有竞争(即 app.datasource.alternate 属性不是 spring.datasource 属性),并应在默认应用程序属性中彼此共存。

    我希望这样的事情能奏效:

    @ConfigurationProperties("app.datasource.alternate")
    public class AlternateDataSourceProperties extends DataSourceProperties {}
    

    但是,当我在yaml中定义属性时:

    app:
      datasource:
        alternate: 
          schema-username: TEST
    

    运行我的测试:

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = NONE)
    @EnableConfigurationProperties({AlternateDataSourceProperties.class})
    public class AlternateDataSourcePropertiesTest {
    
        @Autowired
        // @Qualifier("alternateDataSourceProperties")
        private AlternateDataSourceProperties props;
    
        @Test
        public void propertiesAreInjected() {
            assertThat(props.getSchemaUsername()).isEqualTo("TEST");
        }
    }
    

    程序失败 NoUniqueBeanDefinitionException 当试图创建 datasource 豆子在里面 DataSourceConfiguration.Tomcat 以下内容:

    Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Tomcat.class]: Unsatisfied dependency expressed through method 'dataSource' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' available: expected single matching bean but found 2: app.datasource.alternate-com.example.config.AlternateDataSourceProperties,spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467)
    Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' available: \
      expected single matching bean but found 2: \
      app.datasource.alternate-com.example.config.AlternateDataSourceProperties \
      ,spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
        ... 66 more
    

    我不想重写已经存在的整个属性类,只需要在不同的前缀下添加一组属性。这在弹簧靴中是可能的吗?

    我用的是弹簧靴1.5.x

    更新

    在@prashant答案的启发下,我尝试创建一个额外的配置文件,并将其注入以下内容: @PropertySource("classpath:config/alternate-ds.yml")

    # alternate-ds.yml
    app:
      datasource:
        alternate:
          schema-username: TEST
    
    # AlternateDataSourceProperties.java
    @ConfigurationProperties("app.datasource.alternate")
    @PropertySource("classpath:config/alternate-ds.yml")
    public class AlternateDataSourceProperties extends DataSourceProperties {}
    

    我仍然得到 名词定义例外 现在仍然存在一个竞争的bean资源。有没有一种方法可以指定bean不应该自动连接?

    2 回复  |  直到 7 年前
        1
  •  0
  •   Prashant    7 年前

        public class WebApplication { 
           private static final String CONFIGURATION_FILE_NAME_KEY = "spring.config.name";
           private static final String CONFIGURATION_FILE_NAME_VALUE = new StringJoiner(",")
                .add("application")
                .add("aurora_web")
                .toString();
           private static final String CONFIGURATION_FILE_NAME_PROPERTY = MessageFormat.format("{0}:{1}", CONFIGURATION_FILE_NAME_KEY, CONFIGURATION_FILE_NAME_VALUE);
    
           public static void main(String[] args) {
            new SpringApplicationBuilder(WebApplication.class)
                    .properties(CONFIGURATION_FILE_NAME_PROPERTY)
                    .build()
                    .run(args);
        }
    

    spring.config.name application.[property|yml] @Value() following official documentation .

        2
  •  0
  •   coderatchet    7 年前

    @SpringBootTest 看来这个还可以。

    autowire = Autowire.NO @Bean 自定义属性集的注释,但这仍然提供 NoUniqueBeanDefinitionException

    问题是,春天不知道 DataSourceProperties 数据源属性 @豆子 @Primary

    @Qualifier("alternateDataSourceProperties")

    @Configuration
    public class AlternateDataSourcePropertiesConfiguration {
       @Bean
        @ConfigurationProperties("app.datasource.alternate")
        public DataSourceProperties alternateDataSourceProperties() {
            return new DataSourceProperties();
        }
    
        @Bean
        @Primary
        @ConfigurationProperties("spring.datasource")
        public DataSourceProperties dataSourceProperties() {
            return new DataSourceProperties();
        }
    }
    

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = NONE, properties={"app.datasource.alternate.schema-username=TEST",
    "app.datasource.alternate.username=SOMETHING"})
    @ActiveProfiles("test") // there is a default test datasource configured in application-test.properties so I can test that primary configuration is unaffected. i.e. I have a H2 datasource configured here with username 'sa'
    public class AlternateDataSourcePropertiesConfigurationTest {
    
        @Autowired
        @Qualifier("alternateDataSourceProperties")
        private DataSourceProperties alternateDataSourceProperties;
    
        @Autowired
        private DataSourceProperties primaryDataSourceProperties;
    
        @Test
        public void propertiesAreInjected() {
            assertThat(alternateDataSourceProperties.getSchemaUsername()).isEqualTo("TEST");
        }
    
        @Test
        public void propertiesDontOverridePrimary() {
            assertThat(alternateDataSourceProperties.getUsername()).isEqualTo("SOMETHING");
            assertThat(primaryDataSourceProperties.getUsername()).isEqualTo("sa");
        }
    }