Adnotacja @Conditional

,
Adnotacja @Conditional
Czas czytania: 3 minut

W tym artykule dowiesz się jak w prosty i szybki sposób adnotacja @Conditional, ułatwi Ci tworzenie beanów w Twojej aplikacji w zależności od różnych warunków.

Czasami podczas implementowania aplikacji w Spring’u mamy potrzebę tworzenia bean’ów, tylko jeśli jakiś warunek został spełniony. Może to być dostępność zewnętrznego komponentu (baza danych, inna aplikacja) lub na przykład parametr konfiguracyjny. Co zrobić, jeśli nie chcemy tworzyć konkretnego bean’a w danym momencie lub środowisku?

Spring udostępnia nam adnotację @Conditional, która na podstawie określonego warunku decyduje, czy bean zostanie załadowany do kontekstu aplikacji, co sprawia że jest to bardzo użyteczna funkcjonalność.


Warunkowe deklarowanie bean’a

Adnotacja @Conditional pozwala na utworzenie bean’a tylko w przypadku gdy warunek w niej zawarty zostanie spełniony. Istnieje wiele predefiniowanych wariacji adnotacji @Conditional, o których przeczytasz poniżej, ale podstawowe użycie wygląda następująco.

@Configuration
class ConditionalBeanConfiguration {

  @Bean
  @Conditional(SomeCondition.class)
  ConditionalBean conditionalBean(){
    return new ConditionalBean();
  };
}
public class SomeCondition implements Condition {
@Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Boolean result = //... do something and set result value to true or false
        return result;
    }
}

Bean „ConditionalBean” zostanie utworzony i załadowany do kontekstu aplikacji, tylko jeśli warunek zawarty w klasie „SomeCondition” zostanie spełniony. Klasa „SomeCondition” implementuje interfejs „Condition”, który to dostarcza deklaracji metody „boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata)”. Jeśli metoda „matches” zwróci wartość „true” to bean „ConditionalBean” zostanie utworzony.


Warunkowe tworzenie bean’ów konfiguracyjnych

Możemy używać warunkowego tworzenia bean’ów konfiguracyjnych. Jest to przydatna rzecz podczas pracy na różnych środowiskach (np. deweloperskie, QA, czy też produkcyjne). W poniższym przykładzie żaden bean zdefiniowany w klasie „SomeConfiguration” nie zostanie utworzony, jeśli warunek adnotacji @Conditional nie zostanie spełniony.

@Configuration
@Conditional(SomeCondition.class)
class SomeConfiguration {
  @Bean
  Bean bean(){
    new Bean();
  };
}


Warunkowe tworzenie komponentów

Możemy użyć adnotacji @Conditional do zarządzania tworzeniem beanów typu:

  • @Component
  • @Service
  • @Repository
  • @Controller
@Component
@Conditional(SomeCondition.class)
class SomeComponent {
}


Najpopularniejsze predefiniowane wariacje adnotacji @Conditional

@ConditionalOnProperty – jedna z najbardziej użytecznych adnotacji z tej grupy. Pozwala ona na załadowanie bean’a tylko w przypadku, jeśli parametr konfiguracyjny na to pozwala – jest ustawiony na wartość „true”. Zobacz poniższy przykład użycia:

@Configuration
@ConditionalOnProperty(
    value="some.parameter", 
    havingValue = "true", 
    matchIfMissing = false)
class SomeConfigurations {
  ...
}

Adnotacja @ConditionalOnProperty przyjmuje trzy parametry;

  • value – nazwa parametru konfiguracyjnego.
  • havingValue – wartość, jaką musi przyjąć parametr konfiguracyjny, aby warunek został spełniony.
  • matchIfMissing – domyślna wartość, jeśli parametr konfiguracyjny nie jest ustawiony lub nie istnieje.

@ConditionalOnBean – pozwala na załadowanie bean’a, jeśli inny bean już istnieje w kontekście aplikacji. W poniższym przykładzie bean „RelatedBean” zostanie załadowany, tylko jeśli bean „SomeBean” istnieje już w kontekście aplikacji.

@Configuration
@ConditionalOnBean(SomeBean.class)
class RelatedBean {
  ...
}


@ConditionalOnMissingBean – podobna do poprzedniej adnotacji, z tym że w tym przypadku bean „RelatedBean” zostanie utworzony, jeśli bean „SomeBean” nie istnieje w kontekście aplikacji.

@Configuration
@ConditionalOnMissingBean(SomeBean.class)
class RelatedBean {
  ...
}


@ConditionalOnExperssion – bardzo przydatna wariacja adnotacji @Conditional, która pozwala na zastosowanie skomplikowanych wyrażeń warunkowych z użyciem więcej niż jednego parametru konfiguracyjnego. W poniższym przykładzie bean „SomeBean” zostanie utworzony, tylko jeśli wartości parametrów konfiguracyjnych „some.param1” oraz „some.param2” będą ustawione na „true”.

@Configuration
@ConditionalOnExpression(
    "${some.param1} and ${some.param2}"
)
class SomeBean{
  ...
}


@ConditionalOnResource – umożliwia załadowanie bean’a do kontekstu aplikacji w zależności od tego, czy zasób aplikacji istnieje lub nie. W przykładzie utworzenie beana „LogbackBean” jest uzależnione od istnienia pliku „logback.xml” w katalogu „resources”.

@Configuration
@ConditionalOnResource(resources = "/logback.xml")
class LogbackBean {
  ...
}


@ConditionalOnClass – pozwala na utworzenie bean’a „SomeBean” w zależności od tego, czy klasa „com.arasoftware.does.ExistClass” istnieje.

@Configuration
@ConditionalOnClass(name = "com.arasoftware.does.ExistClass")
class SomeBean {
  ...
}


@ConditionalOnMissingClass – analogicznie do poprzedniej adnotacji, z tym że tutaj bean „SomeBean” zostanie utworzony, jeśli klasa „com.arasoftware.does.ExistClass” nie istnieje.

@Configuration
@ConditionalOnMissingClass(name = "com.arasoftware.does.ExistClass")
class SomeBean {
  ...
}


@ConditionalOnJava – pozwala na utworzenie bean’a w zależności od wersji Javy, z której aktualnie używamy. Jest to bardzo przydatna adnotacjach podczas refactoringu aplikacji „legacy”.

@Configuration
@ConditionalOnJava(JavaVersion.EIGHT)
class SomeBean{
  ...
}


Podsumowanie

Jak widać mamy do dyspozycji całkiem sporo różnego rodzaju wariantów adnotacji @Conditional, ponieważ twórcy Springa pomyśleli o tym żeby maksymalnie ułatwić korzystanie z tej adnotacji. Pozwalają one odpowiednio konfigurować aplikację w zależności od jej zasobów czy też środowiska, co czyni ten mechanizm bardzo łatwym w użyciu.

Przydatne materiały:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Conditional.html

Jeśli podobał Ci się ten artykuł, to proszę, podziel się nim z innymi na swoich social mediach!

Czy ten post był dla Ciebie pomocny?

Kliknij na gwiazdki żeby zagłosować.

Średnia ocena 5 / 5. Liczba głosów: 2

Brak głosów do tej pory. Bądź pierwszy(a)!

Bardzo mi przykro że ten post nie był dla Ciebie pomocny 🙁

Pozwól mi poprawić ten post!

Powiedz mi co mogę poprawić?