2017-01-28 7 views
2

私は、ユーザが指定するプロパティに基づいて自動的にBeanを作成するSpring Boot 1.4.3 @AutoConfigurationを使用しています。ユーザーは、サービスの配列、バージョンが必要とされているフィールドを指定することができます。ユーザーはでも一つだけのサービスに必要なフィールドを指定するのを忘れた場合はリストや配列の@ConditionalOnProperty?

service[0].name=myServiceA 
service[0].version=1.0 

service[1].name=myServiceB 
service[1].version=1.2 

... 

を、私はバックオフをしたくありません任意のBeanを作成します。 @ConditionalOnPropertyでこれを達成できますか?私は次のようなものを求めています:

@Configuration 
@ConditionalOnProperty({"service[i].name", "service[i].version"}) 
class AutoConfigureServices { 
.... 
} 
+1

と私のConfigurationクラスを注釈付きそこにスローされた例外(コンストラクタに明示的に、またはSpringが存在をチェックする場合は暗黙的に) – chrylis

+0

それは良い考えです。 Beanがインスタンス化される前にコンストラクタがautoconfigureクラスで実行されると、どうにかしてBeanが作成されるのを防ぐことができますか?残念ながら、私は例外をスローすることはできません原因は、致命的ではない小道具を忘れている。 – Strumbles

+0

なぜですか?半構成のBeanがあります。 – chrylis

答えて

0

これはカスタムですCondition私は作成しました。より一般的な(ハードコード文字列ではない)研磨が必要ですが、私にとってはうまくいっています。しかし、あなたは、コンストラクタでこれらの値を設定している場合は、あなたが得ることができる - 使用するには

、私は*これは、それ自体が有効である*とは思わない@Conditional(RequiredRepeatablePropertiesCondition.class)

public class RequiredRepeatablePropertiesCondition extends SpringBootCondition { 

    private static final Logger LOGGER = LoggerFactory.getLogger(RequiredRepeatablePropertiesCondition.class.getName()); 

    public static final String[] REQUIRED_KEYS = { 
      "my.services[i].version", 
      "my.services[i].name" 
    }; 

    @Override 
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { 
     List<String> missingProperties = new ArrayList<>(); 
     RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(context.getEnvironment()); 
     Map<String, Object> services = resolver.getSubProperties("my.services"); 
     if (services.size() == 0) { 
      missingProperties.addAll(Arrays.asList(REQUIRED_KEYS)); 
      return getConditionOutcome(missingProperties); 
     } 
     //gather indexes to check: [0], [1], [3], etc 
     Pattern p = Pattern.compile("\\[(\\d+)\\]"); 
     Set<String> uniqueIndexes = new HashSet<String>(); 
     for (String key : services.keySet()) { 
      Matcher m = p.matcher(key); 
      if (m.find()) { 
       uniqueIndexes.add(m.group(1)); 
      } 
     } 
     //loop each index and check required props 
     uniqueIndexes.forEach(index -> { 
      for (String genericKey : REQUIRED_KEYS) { 
       String multiServiceKey = genericKey.replace("[i]", "[" + index + "]"); 
       if (!resolver.containsProperty(multiServiceKey)) { 
        missingProperties.add(multiServiceKey); 
       } 
      } 
     }); 
     return getConditionOutcome(missingProperties); 
    } 

    private ConditionOutcome getConditionOutcome(List<String> missingProperties) { 
     if (missingProperties.isEmpty()) { 
      return ConditionOutcome.match(ConditionMessage.forCondition(RequiredRepeatablePropertiesCondition.class.getCanonicalName()) 
        .found("property", "properties") 
        .items(Arrays.asList(REQUIRED_KEYS))); 
     } 
     return ConditionOutcome.noMatch(
       ConditionMessage.forCondition(RequiredRepeatablePropertiesCondition.class.getCanonicalName()) 
      .didNotFind("property", "properties") 
      .items(missingProperties) 
     ); 
    } 
}