# Spring Boot Conditional Bean Loading

# Introduction 

It is possible to achieve conditional bean loading based on both property values and complex expressions in Spring Boot. While the `@ConditionalOnProperty` and `@ConditionalOnExpression` annotations are not repeatable on the same element, you can combine their functionality.


# Combining `@ConditionalOnProperty` and `@ConditionalOnExpression`:

The most common approach to combine these conditions is to use a single `@ConditionalOnExpression` annotation that incorporates both property checks and more complex expressions using Spring Expression Language (SpEL).

For example, to check for the presence and value of a property while also evaluating a more complex condition:
```
@Configuration
@ConditionalOnExpression("${my.feature.enabled:false} && T(java.time.LocalDate).now().getDayOfWeek().getValue() == 5")
public class MyConditionalConfiguration {
    // ... bean definitions ...
}
```

In this example:

-   `${my.feature.enabled:false}` checks the value of the `my.feature.enabled` property, defaulting to `false` if not present.
-   `T(java.time.LocalDate).now().getDayOfWeek().getValue() == 5` is a SpEL expression that checks if the current day of the week is Friday (where 5 represents Friday).
-   The `&&` operator ensures both conditions must be true for the configuration to be loaded.

# Alternative using `@Conditional` and custom `Condition` implementations:

For more complex or reusable conditional logic, you can implement the `org.springframework.context.annotation.Condition` interface and use it with the general `@Conditional` annotation. This allows you to encapsulate detailed logic for property checks, expression evaluations, or any other custom conditions within a dedicated class.

```
public class MyCustomCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // Implement complex logic here, combining property checks and expressions
        boolean propertyEnabled = context.getEnvironment().getProperty("my.feature.enabled", Boolean.class, false);
        boolean isFriday = java.time.LocalDate.now().getDayOfWeek().getValue() == 5;
        return propertyEnabled && isFriday;
    }
}

@Configuration
@Conditional(MyCustomCondition.class)
public class MyConditionalConfiguration {
    // ... bean definitions ...
}
```
This approach provides greater flexibility and maintainability for intricate conditional requirements.

# Conclusion

Spring's conditional annotations, including `@ConditionalOnProperty`, `@ConditionalOnExpression`, and the more general `@Conditional`, provide powerful mechanisms for dynamically managing the application context and load beans depending on your most complex use cases.
