Home > database >  @Conditional matches method is invoked n 1 times
@Conditional matches method is invoked n 1 times

Time:01-27

Why boolean matches(...) method in SpecificCaseCondition class is invoked 2 times ? I expect it to be invoked only once, on AnyConfiguration creation. In fact, it's invoked 2 times.

public class SpecificCaseCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return true;
    }
}


@Configuration
@Conditional(SpecificCaseCondition.class)
public class AnyConfiguration {

    @Bean
    public Service firstService() {
        return new RealService();
    }
    
    @Bean
    public Service secondService() {
        return new RealService();
    }
    
    @Bean
    public Service thirdService() {
        return new RealService();
    }
}

CodePudding user response:

When Spring Boot auto-configures the beans for the app context, it does so in multiple phases. By default, condition at the class level* will be evaluated multiple times, for each phase. That's probably why you're seeing your custom Condition method being called more than once; Spring is invoking it during each phase.

One way to avoid that would be to annotate the @Bean methods with @Conditional instead of the entire class. Like this:

@Configuration
public class AnyConfiguration {

    @Bean
    @Conditional(SpecificCaseCondition.class)
    public Service firstService() {
        return new RealService();
    }
    
    @Bean
    @Conditional(SpecificCaseCondition.class)
    public Service secondService() {
        return new RealService();
    }
    
    @Bean
    @Conditional(SpecificCaseCondition.class)
    public Service thirdService() {
        return new RealService();
    }
}

In my experiments, method-level conditions are only evaluated during the REGISTER_BEAN phase.

There is a downside to this solution, of course - it isn't very DRY. As an alternative, you can change your condition to implement ConfigurationCondition which has a method, public ConfigurationPhase getConfigurationPhase(), to dictate which phase the condition should be evaluated in.


  • The various @Conditional* annotations can be placed at the class level or the method level.
  • Related