Spring @ConditionalOnBean is not finding the the bean

Viewed 275

I am using spring boot: 2.5.7

I have a starter in my application that is not working. I opened the code in order to understand the reason and notice a weird behavior:

The starter code is:

AutoConfiguration:

@Configuration
@EnableConfigurationProperties(MyConfigProperties.class)
public class MyCompanyAutoConfiguration {


  @Bean
  @ConditionalOnBean(MyConfigProperties.class)
  public MeterRegistry defaultNewRelicMeterRegistry(MyConfigProperties config) {
    System.out.println("called method");
    return MyCompanyNewRelicRegistry.builder(config).build();
  }

}

PropertyBean

@Configuration
@ConfigurationProperties(prefix = "company.config.newrelic")
@ConditionalOnProperty(prefix = "company.config.newrelic", name = "apiKey")
@ConditionalOnClass(NewRelicRegistryConfig.class)
public class MyConfigProperties implements NewRelicRegistryConfig {

   // getters and setters
   ...
}

Factory file (spring.factories)

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.company.MyCompanyAutoConfiguration

When I start my application, MyCompanyNewRelicRegistry bean is not been created.

I find out that "ConditionalOnBean" is the problem, the code does not print "called method" when use this annotation. It is weird because MyConfigProperties bean is initialized (I saw calling the applicationContext.getBean after container have started).

When I remove the annotation @ConditionalOnBean, everything works well and the method is called.

Why ConditionalOnBean is not finding MyConfigProperties that time?

Note: all properties and classes used in other conditions are ok.

# UPDATE

I changed to:

@Configuration
@EnableConfigurationProperties
@ComponentScan
public class MyCompanyAutoConfiguration {


  @Bean
  @ConditionalOnBean(MyConfigProperties.class)
  public MeterRegistry defaultNewRelicMeterRegistry(MyConfigProperties config) {
    System.out.println("called method");
    return MyCompanyNewRelicRegistry.builder(config).build();
  }

}

The above example works.

I saw in log that spring try to load "defaultNewRelicMeterRegistry" first, when evaluate the conditionalBean, its not created yet.

When I remove the ConditionalOnBean the spring will load the property in order to inject it.

May the componentScan "force" spring to load all other beans before the declared bean in autoconfiguration class, make sense?

0 Answers
Related