30 Mayıs 2018 Çarşamba

SpringContext @Conditional Anotasyonu - Condition Nesnesi True İse Bean Yaratılır

Giriş
Condition arayüzünden kalıtan bir sınıf kodlarız. Bu sınıfı @Conditional ile birlikte kullanırız. Eğer Condition sınıfımız true dönerse bean yaratılır

Hazır gelen Condition nesneleri şöyle
- OnPropertyCondition

@Conditional vs @ConditionalOnBean
Açıklaması şöyle. Önce @ConditionalOnBean çalışır ve bean yaratılmasını kontrol eder. Sonra @Conditional çalışır ve bean'i kaydeder
While @ConditionalOnBean might appear similar to @Conditional, they operate at different phases of the application context lifecycle. @ConditionalOnBean checks conditions during bean creation, whereas @Conditional evaluates conditions before the bean definition is registered.
Condition Arayüzü
public interface Condition {
  boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
Açıklaması şöyle
ConditionContext: Provides context information during the evaluation, including details about the bean factory, environment, and class loader.
AnnotatedTypeMetadata: Offers metadata of the annotated element, which can be a class, method, or field.
Örnek - System Property
Şöyle yaparız
public class MySimpleCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    String enabled = System.getProperty("enableMyBean");
    return "true".equalsIgnoreCase(enabled);
  }
}
Örnek - Environment Property
Şöyle yaparız
public class CustomPropertyCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Environment env = context.getEnvironment();
    return env.containsProperty("my.custom.property");
  }
}
Örnek - Profile + Environment Property
Şöyle yaparız
public class ProfileAndPropertyCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Environment env = context.getEnvironment();
    return env.acceptsProfiles("production") 
      && env.containsProperty("enableSpecialFeature");
  }
}
Örnek - Annotation
Şöyle yaparız. Burada @Conditional anotasyonunu kullanıldığı yerdeki diğer anotasyonlara erişiliyor
public class RoleBasedCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Map<String, Object> attributes = metadata
      .getAnnotationAttributes(RoleConditional.class.getName());
    String requiredRole = (String) attributes.get("value");
    
    // Your logic to check if the current user has the required role
    return checkUserRole(requiredRole);
  }
  
  private boolean checkUserRole(String requiredRole) {
    // Custom logic to check user role
    return true; // Or false, based on your evaluation
  }
}
@Conditional Anotasyonu Kullanımı
1. Bu anotasyon sınıf veya metod seviyesinde kullanılabilir
2. Bu anotasyon birden fazla Condition nesnesi alabilir

Örnek - Sınıf Seviyesi
Elimizde şöyle bir kod olsun
public class StopWatchOnOffCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata arg1) {
    ...
  }
}
Şöyle yaparız.
@Conditional(value = { StopWatchOnOffCondition.class })
@Service
public class StopWatchService {...}
Örnek - Sınıf Seviyesi ve Sınıf İçinde Beanler
Elimizde şöyle bir kod olsun. Burada Condition false ise sınıf içindeki bean'ler de yaratılmaz. Yani @KafkaListener ve @Scheduled çalışmaz.
@Component
@Conditional(MessageQueueEnabledCondition.class)
public class MyMessageListener {

  @KafkaListener(topics = "myTopic")
  public void listen(String message) {
    // Do something
  }
}

@Component
@Conditional(GeolocationCondition.class)
public class GeolocationBasedScheduler {

  @Scheduled(fixedRate = 5000)
  public void executeTaskBasedOnGeolocation() {
    // Task execution logic
  }
}
Örnek - Çoklu Condition
Şöyle yaparız
@Bean
@Conditional({DatabaseAvailableCondition.class, EmailServiceEnabledCondition.class})
public MyService myService() {
  return new MyServiceImpl();
}
Örnek - Aynı Bean İki Defa - Kullanmayın
Şöyle yaparız. Burada her iki condition da true ise MyService iki defa kaydedilir ancak sonuncusu diğerlerini ezer. Yani myProdService kullanılır
@Bean
@Conditional(OnDevelopmentCondition.class)
public MyService devMyService() {
  return new DevMyService();
}

@Bean
@Conditional(OnProductionCondition.class)
public MyService prodMyService() {
  return new ProdMyService();
}


Hiç yorum yok:

Yorum Gönder