使用多个相同类型的bean进行自定义自动配置

时间:2019-06-14 14:36:16

标签: spring-boot

使用spring-boot-2,我想创建一个自定义自动配置,该动态配置定义动态数量的相同类型的bean。

例如,我有以下ConfigurationProperties来定义AmazonS3客户

@Setter
@Getter
@ConfigurationProperties("aws")
public class S3ClientProperties {
    private Map<String, S3Config> s3 = new HashMap<>();

    @Setter
    @Getter
    public static class S3Config {
        private String accessKey;
        private String secretKey;
        private String bucketName;
        private String region;
        // ...
    }
}

如果我有这样的Yaml:

aws.s3:
  primary:
    bucketName: bucket1
    region: eu-west-1
  secondary:
    bucketName: bucket2
    region: eu-east-1

最好将2个AmazonS3类型的Bean注册到ApplicationContext,一个名为primary,一个名为secondary。 >

除了在我的@PostContstruct上放置@Configuration,自动装配上下文并手动添加这些bean之外,还有其他更方便/更好的方法吗?

1 个答案:

答案 0 :(得分:0)

您可以使用ConditionalOnProperty或多个条件,简单的例子(与您的yaml一起使用):

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);

        Map<String, SomeService> someServiceBeans = context.getBeansOfType(SomeService.class);

        someServiceBeans.forEach((key, value) ->
                System.out.println("bean name: " + key + " ,bean class: " + value.getClass().getSimpleName()));
    }

    // some service
    public interface SomeService {

    }

    // service if `aws.s3.primary` property exists
    @Service("primaryService")
    @ConditionalOnProperty("aws.s3.primary.bucketName")
    public static class SomePrimaryService implements SomeService {

    }

    // service if `aws.s3.secondary` property exists
    @Service("secondaryService")
    @ConditionalOnProperty("aws.s3.secondary.bucketName")
    public static class SomeSecondaryService implements SomeService {

    }

    // service if `SomeService` bean missing ( `aws.s3.primary` & `aws.s3.secondary` not exists )
    @Service("defaultService")
    @ConditionalOnMissingBean(SomeService.class)
    public static class SomeDefaultService implements SomeService {

    }

    // service with `custom` condition and `class` condition (multiple conditions)
    @Service("customService")
    @ConditionalOnCustom
    @ConditionalOnClass(SomeDefaultService.class)
    public static class SomeCustomService implements SomeService {

    }

    // annotation for custom condition
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Conditional(CustomCondition.class)
    public @interface ConditionalOnCustom {

    }

    // any custom condition
    public static class CustomCondition implements Condition {

        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            // do something
            return true;
        }

    }

}

应用程序输出:

bean name: customService ,bean class: SomeCustomService
bean name: primaryService ,bean class: SomePrimaryService
bean name: secondaryService ,bean class: SomeSecondaryService

还可以看看Creating Your Own Auto-configuration