@ConditionalOnPropertyによる条件付きBeanの定義
Spring Bootアプリケーションでは、特定の条件に基づいてBeanを登録したり、設定クラスを有効にしたりすることができます。その中でも、アプリケーションのプロパティ値に基づいてコンポーネントの有効/無効を切り替える際に非常に便利なのが@ConditionalOnPropertyアノテーションです。
このアノテーションは、指定されたプロパティが存在し、かつその値が期待される値と一致する場合にのみ、関連するBeanや@Configurationクラスをロードします。プロパティが存在しない場合や、値が一致しない場合には、それらのコンポーネントはアプリケーションコンテキストに登録されません。
基本的な使用例
例えば、特定の機能の有効/無効をアプリケーションプロパティで制御したい場合を考えます。まず、application.properties(またはapplication.yml)に次のようなプロパティを定義します。
app.feature.enabled=true
次に、このプロパティに基づいてBeanの生成を制御する設定クラスを作成します。
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
@Configuration
@ConditionalOnProperty(
prefix = "app.feature",
name = "enabled",
havingValue = "true",
matchIfMissing = false
)
public class FeatureActivationConfiguration {
// このサービスは 'app.feature.enabled=true' の場合にのみBeanとして登録されます
@Bean
public MyFeatureService myFeatureService() {
return new MyFeatureService();
}
public static class MyFeatureService {
public String getFeatureStatus() {
return "特定機能サービスが有効になりました。";
}
}
}
上記の例では、app.feature.enabledというプロパティが存在し、その値が"true"である場合にのみ、FeatureActivationConfigurationクラス全体が有効になり、myFeatureServiceというBeanがSpringコンテキストに登録されます。
条件付きBeanの利用
この条件付きで登録されるサービスをアプリケーション内で利用する際は、通常通りDI (Dependency Injection) を行います。ただし、Beanが登録されない可能性を考慮し、存在チェックや@Autowired(required = false)を使用することが望ましいです。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@SpringBootApplication
public class PropertyConditionalApplication {
public static void main(String[] args) {
SpringApplication.run(PropertyConditionalApplication.class, args);
}
@Component
public static class ApplicationStartupRunner implements CommandLineRunner {
private final ApplicationContext applicationContext;
@Autowired
public ApplicationStartupRunner(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void run(String... args) {
// MyFeatureServiceがBeanとして存在するか確認
if (applicationContext.containsBean("myFeatureService")) {
FeatureActivationConfiguration.MyFeatureService service =
applicationContext.getBean(FeatureActivationConfiguration.MyFeatureService.class);
System.out.println(service.getFeatureStatus());
} else {
System.out.println("特定機能サービスは現在無効です。");
}
}
}
}
このコードを実行すると、application.propertiesでapp.feature.enabled=trueが設定されていれば「特定機能サービスが有効になりました。」と出力され、それ以外の場合は「特定機能サービスは現在無効です。」と出力されます。
@ConditionalOnPropertyアノテーションの主要属性
prefix: プロパティ名のプレフィックスを指定します。例えば「app.feature」のように指定すると、後のname属性で指定するプロパティが「app.feature.enabled」のように解決されます。name: 条件を適用するプロパティのキーを指定します。prefixと組み合わせて完全なプロパティ名が形成されます。複数のプロパティ名を指定することも可能です。havingValue: プロパティ値がこの値と一致する場合にBeanが作成されます。値が指定されない場合(デフォルト)、プロパティが存在し、その値が"false"ではない場合にBeanが作成されます。matchIfMissing:trueに設定すると、指定されたプロパティが存在しない場合でもBeanが作成されます。デフォルトはfalseです。
その他の条件付きアノテーション
Spring Bootには、@ConditionalOnProperty以外にも様々な条件付きアノテーションが用意されています。これらを活用することで、さらに柔軟なコンポーネントの条件付きロードが可能です。
@ConditionalOnClass@ConditionalOnMissingClass@ConditionalOnBean@ConditionalOnMissingBean@ConditionalOnResource@ConditionalOnWebApplication@ConditionalOnNotWebApplication@ConditionalOnJava@ConditionalOnExpression@ConditionalOnJndi@ConditionalOnCloudPlatform@ConditionalOnSingleCandidate