春の条件付き注釈
1. 序章
このチュートリアルでは、@Conditionalアノテーションを見ていきます。 定義された条件に基づいて、特定のコンポーネントが登録に適格かどうかを示すために使用されます。
事前定義された条件付きアノテーションを使用する方法、それらをさまざまな条件と組み合わせる方法、およびカスタムの条件ベースのアノテーションを作成する方法を学習します。
2. 条件の宣言
実装に移る前に、まず、どのような状況で条件付きアノテーションを利用できるかを見てみましょう。
最も一般的な使用法は、構成クラス全体を含めるか除外することです。
@Configuration
@Conditional(IsDevEnvCondition.class)
class DevEnvLoggingConfiguration {
// ...
}
または、単一のBean:
@Configuration
class DevEnvLoggingConfiguration {
@Bean
@Conditional(IsDevEnvCondition.class)
LoggingService loggingService() {
return new LoggingService();
}
}
そうすることで、アプリケーションの動作を特定の条件に基づいて行うことができます。 たとえば、環境のタイプやクライアントの特定のニーズ。 上記の例では、開発環境に対してのみ追加のロギングサービスを初期化します。
コンポーネントを条件付きにする別の方法は、条件をコンポーネントクラスに直接配置することです。
@Service
@Conditional(IsDevEnvCondition.class)
class LoggingService {
// ...
}
上記の例は、 @Component 、 @Service 、 @Repository、、または@Controllerアノテーションで宣言された任意のBeanに適用できます。
3. 事前定義された条件付き注釈
Springには、事前定義された条件付きアノテーションのセットが付属しています。 最も人気のあるもののいくつかを見てみましょう。
まず、構成プロパティ値に基づいてコンポーネントをベースにする方法を見てみましょう:
@Service
@ConditionalOnProperty(
value="logging.enabled",
havingValue = "true",
matchIfMissing = true)
class LoggingService {
// ...
}
最初の属性value、は、表示する構成プロパティを示します。 2番目のhavingValue、は、この条件に必要な値を定義します。 最後に、 matchIfMissing 属性は、パラメーターが欠落している場合に条件を一致させる必要があるかどうかをSpringに通知します。
同様に、式に基づいて条件を設定できます。
@Service
@ConditionalOnExpression(
"${logging.enabled:true} and '${logging.level}'.equals('DEBUG')"
)
class LoggingService {
// ...
}
これで、Springは logging.enabled構成プロパティがtrue、とlogging.levelの両方に設定されている場合にのみLoggingServiceを作成します。 DEBUGに設定されています。
適用できるもう1つの条件は、特定のBeanが作成されたかどうかを確認することです。
@Service
@ConditionalOnBean(CustomLoggingConfiguration.class)
class LoggingService {
// ...
}
または、特定のクラスがクラスパスに存在します。
@Service
@ConditionalOnClass(CustomLogger.class)
class LoggingService {
// ...
}
@ConditionalOnMissingBeanまたは@ConditionalOnMissingClassアノテーションを適用することで、逆の動作を実現できます。
さらに、コンポーネントを特定のJavaバージョンに依存させることができます。
@Service
@ConditionalOnJava(JavaVersion.EIGHT)
class LoggingService {
// ...
}
上記の例では、 LoggingService は、ランタイム環境がJava8の場合にのみ作成されます。
最後に、 @ConditionalOnWarDeployment アノテーションを使用して、戦争パッケージでのみBeanを有効にすることができます。
@Configuration
@ConditionalOnWarDeployment
class AdditionalWebConfiguration {
// ...
}
サーバーが組み込まれているアプリケーションの場合、この条件はfalseを返すことに注意してください。
4. カスタム条件の定義
Springでは、カスタム条件テンプレートを作成することにより、@Conditionalアノテーションの動作をカスタマイズできます。 作成するには、Conditionインターフェイスを実装する必要があります。
class Java8Condition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return JavaVersion.getJavaVersion().equals(JavaVersion.EIGHT);
}
}
matches メソッドは、条件が合格したかどうかをSpringに通知します。 これには、Beanが初期化されるコンテキストと、使用される@Conditionalアノテーションのメタデータに関する情報をそれぞれ提供する2つの引数があります。
ご覧のとおり、この例では、Javaのバージョンが8であるかどうかを確認するだけです。
その後、新しい条件を@Conditionalアノテーションの属性として配置する必要があります。
@Service
@Conditional(Java8Condition.class)
public class Java8DependedService {
// ...
}
このように、 Java8DependentService は、Java8Conditionクラスの条件が一致する場合にのみ作成されます。
5. 組み合わせ条件
より複雑なソリューションの場合、ORまたはAND論理演算子を使用して条件付き注釈をグループ化できます。
OR演算子を適用するには、AnyNestedConditionクラスを拡張するカスタム条件を作成する必要があります。 その中に、条件ごとに空の static クラスを作成し、適切な@Conditional実装で注釈を付ける必要があります。
たとえば、Java8またはJava9のいずれかを必要とする条件を作成しましょう。
class Java8OrJava9 extends AnyNestedCondition {
Java8OrJava9() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@Conditional(Java8Condition.class)
static class Java8 { }
@Conditional(Java9Condition.class)
static class Java9 { }
}
一方、AND演算子ははるかに単純です。 条件を簡単にグループ化できます。
@Service
@Conditional({IsWindowsCondition.class, Java8Condition.class})
@ConditionalOnJava(JavaVersion.EIGHT)
public class LoggingService {
// ...
}
上記の例では、 LoggingService は、IsWindowsConditionとJava8Conditionの両方が一致する場合にのみ作成されます。
6. 概要
この記事では、条件付きアノテーションの使用方法と作成方法を学びました。 いつものように、すべてのソースコードはGitHubで利用できます。