プロファイルのグループで使用されないようにBeanを構成することはできますか?現在私はこれを行うことができます(私は信じています):
@Profile("!dev, !qa, !local")
これを達成するためのきちんとした表記はありますか?プロファイルがたくさんあるとしましょう。また、いくつかのサービス(または何でも)のモックおよび具体的な実装がある場合、それらの1つに注釈を付けるだけで、他のすべてのケースでもう1つが使用されると想定できますか?言い換えれば、これはたとえば必要ですか?
@Profile("dev, prof1, prof2")
public class MockImp implements MyInterface {...}
@Profile("!dev, !prof1, !prof2") //assume for argument sake that there are many other profiles
public class RealImp implements MyInterface {...}
そのうちの1つに注釈を付けて、@Primary
もう一方にアノテーションを付けますか?
本質的に私はこれが欲しい:
@Profile("!(dev, prof1, prof2)")
前もって感謝します!
短い答えは:できません。
しかし、@Conditional
アノテーションのおかげで存在するきちんとした回避策があります。
public abstract class ProfileCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
if (matchProfiles(conditionContext.getEnvironment())) {
return ConditionOutcome.match("A local profile has been found.");
}
return ConditionOutcome.noMatch("No local profiles found.");
}
protected abstract boolean matchProfiles(final Environment environment);
}
public class DevProfileCondition extends ProfileCondition {
private boolean matchProfiles(final Environment environment) {
return Arrays.stream(environment.getActiveProfiles()).anyMatch(prof -> {
return prof.equals("dev") || prof.equals("prof1")) || prof.equals("prof2"));
});
}
}
public class ProdProfileCondition extends ProfileCondition {
private boolean matchProfiles(final Environment environment) {
return Arrays.stream(environment.getActiveProfiles()).anyMatch(prof -> {
return !prof.equals("dev") && !prof.equals("prof1")) && !prof.equals("prof2"));
});
}
}
@Conditional(value = {DevProfileCondition.class})
public class MockImpl implements MyInterface {...}
@Conditional(value = {ProdProfileCondition.class})
public class RealImp implements MyInterface {...}
ただし、このアプローチにはSpringbootが必要です。
私が理解していることから、あなたがしたいことは、特定のプロファイルについて、いくつかのBeanをいくつかのスタブ/モックBeanに置き換えることができることです。これに対処するには2つの方法があります。
最初のオプションは実現可能ですが困難です。これは、@Profile
アノテーションで複数のプロファイルを提供する場合のSpringのデフォルトの動作がOR
条件であるためです(ケースで必要なAND
ではありません)。この理想的なSpringの動作はより直観的です。理想的には、各プロファイルはアプリケーションの各構成(実稼働、単体テスト、統合テストなど)に対応している必要があるため、常に1つのプロファイルのみがアクティブになる必要があります。これがORがプロファイル間でAND
よりも理にかなっている理由です。この結果、おそらくプロファイルをネストすることにより、この制限を回避できますが、構成が非常に複雑で保守性が低い。
したがって、2番目のアプローチを使用することをお勧めします。アプリケーションの構成ごとに1つのプロファイルを用意します。すべての構成で同じであるすべてのBeanは、@Profile
が指定されていないクラスに常駐できます。その結果、これらのBeanはすべてのプロファイルによってインスタンス化されます。異なる構成ごとに区別する必要がある残りのBeanについては、@Configuration
が対応するプロファイルに設定されたすべての@Profile
クラスを(Springプロファイルごとに)個別に作成する必要があります。このようにして、どんな場合でも注入されるものを簡単に処理できます。
これは次のようになります。
@Profile("dev")
public class MockImp implements MyInterface {...}
@Profile("prof1")
public class MockImp implements MyInterface {...}
@Profile("prof2")
public class MockImp implements MyInterface {...}
@Profile("the-last-profile") //you should define an additional profile, not rely on excluding as described before
public class RealImp implements MyInterface {...}
最後に、@Primary
アノテーションを使用して、既存のBeanをオーバーライドします。同じタイプのBeanが2つある場合、@Primary
アノテーションがないと、Springからインスタンス化エラーが発生します。いずれかのBeanに@Primary
アノテーションを定義した場合、エラーは発生せず、このBeanはこのタイプが必要なすべての場所に挿入されます(他のBeanは無視されます)。ご覧のとおり、これは単一のプロファイルがある場合にのみ役立ちます。そうでなければ、これも最初の選択肢として複雑になります。
TL; DR:はい、できます。タイプごとに、プロファイルごとに1つのBeanを定義し、このプロファイルのみで@Profile
アノテーションを追加します。