Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-14603

Invalid WARN when returning a BeanDefinitionRegistryPostProcessor from within a @Configuration class

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Complete
    • Affects Version/s: None
    • Fix Version/s: 4.3.11, 5.0 RC4
    • Component/s: Core
    • Labels:
      None
    • Last commented by a User:
      true

      Description

      Consider the following configuration class:

      import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
       
      @Configuration
      public class MyConfiguration {
       
          @Bean
          public static BeanDefinitionRegistryPostProcessor myPostProcessor() {
              return new MyBeanDefinitionPostProcessor();
          }
      }
      

      (if it matters, this class is loaded in Spring MVC and Spring Boot applications via an @Import(MyConfiguration.class) annotation.)

      This causes a WARN message to be printed as follows:

      Cannot enhance @Configuration bean definition 'myPostProcessor' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.

      As you can see, the method is declared as static, yet I still receive the WARN message. When I remove the static modifier, I still receive the same WARN message. Something is amiss.

      This is a problem for us because we use this code in a Spring library as well as a Spring Boot starter/plugin that we distribute to customers - when they see the WARN message, they think something is wrong, even though everything is working as expected.

        Issue Links

          Activity

          Hide
          lhazlewood Les Hazlewood added a comment -

          I commented out the @Import approach and tried as a nested static class to see if that would help:

          //@Import(MyConfiguration.class)
          @Configuration
          public class SomeConfiguration {
           
              @Configuration
              public static class MyConfiguration {
                  @Bean
                  public static BeanDefinitionRegistryPostProcessor myPostProcessor() {
                      return new MyBeanDefinitionPostProcessor();
                  }
              }
           
              //other non-relevant @Bean definitions here...
          }
          

          This didn't work either - same WARN message.

          Show
          lhazlewood Les Hazlewood added a comment - I commented out the @Import approach and tried as a nested static class to see if that would help: //@Import(MyConfiguration.class) @Configuration public class SomeConfiguration {   @Configuration public static class MyConfiguration { @Bean public static BeanDefinitionRegistryPostProcessor myPostProcessor() { return new MyBeanDefinitionPostProcessor(); } }   //other non-relevant @Bean definitions here... } This didn't work either - same WARN message.
          Hide
          juergen.hoeller Juergen Hoeller added a comment -

          What does your post-processor implementation class look like? The warn message suggests that the post-processor class itself is marked with @Configuration...

          Show
          juergen.hoeller Juergen Hoeller added a comment - What does your post-processor implementation class look like? The warn message suggests that the post-processor class itself is marked with @Configuration ...
          Hide
          t.vahrst Thomas Vahrst added a comment - - edited

          I get the same warning, when I try to define a BeanDefinitionRegistryPostProcessor as static @Bean method. It seems, thas every BeanDefinition of static defined Beans gets an BeanDefinition attribute org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass = full, because

          in ConfigClassBeanDefinitionReader :

          	private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
          ..
          		if (metadata.isStatic()) {
          			// static @Bean method
          			beanDef.setBeanClassName(configClass.getMetadata().getClassName());
          			beanDef.setFactoryMethodName(methodName);
          		}
          		else {
          
          

          The beanClassName in the beandefinition is set to configClass' classname

          and later in ConfigurationClassUtils:

          	public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
           
          ...
          		if (isFullConfigurationCandidate(metadata)) {
          			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
          		}
          

          This seems not to be problem for 'normal' beans, but if the bean type is BeanDefinitionRegistryFactoryPostProcessor, it is instantiated very early. This in turn leads to the warning in ConfigurationClassPostProcessor.enhanceConfigurationClasses becauce both conditions

          • .isFullConfigurationClass AND
          • beanFactory.containsSinglenton
            are true.
          Show
          t.vahrst Thomas Vahrst added a comment - - edited I get the same warning, when I try to define a BeanDefinitionRegistryPostProcessor as static @Bean method. It seems, thas every BeanDefinition of static defined Beans gets an BeanDefinition attribute org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass = full , because in ConfigClassBeanDefinitionReader : private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { .. if (metadata.isStatic()) { // static @Bean method beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(methodName); } else { The beanClassName in the beandefinition is set to configClass' classname and later in ConfigurationClassUtils: public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {   ... if (isFullConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); } This seems not to be problem for 'normal' beans, but if the bean type is BeanDefinitionRegistryFactoryPostProcessor , it is instantiated very early. This in turn leads to the warning in ConfigurationClassPostProcessor.enhanceConfigurationClasses becauce both conditions .isFullConfigurationClass AND beanFactory.containsSinglenton are true.
          Hide
          t.vahrst Thomas Vahrst added a comment -

          Our workaround:
          put the BeanDefinitionPostProcessor class in a special sub-package, annotate it with @Component und define @ComponentScan(basePackages=...) in the config class.

          Show
          t.vahrst Thomas Vahrst added a comment - Our workaround: put the BeanDefinitionPostProcessor class in a special sub-package, annotate it with @Component und define @ComponentScan(basePackages=...) in the config class.

            People

            • Assignee:
              juergen.hoeller Juergen Hoeller
              Reporter:
              lhazlewood Les Hazlewood
              Last updater:
              St├ęphane Nicoll
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                7 weeks, 5 days ago