Warn about non-static ConfigurationClassPostProces

2020-06-02 13:23发布

问题:

I use Spring 4.2.6.RELEASE. During initialization of my app I get such a warning:

[WARN] org.springframework.context.annotation.ConfigurationClassPostProcessor enhanceConfigurationClasses: Cannot enhance @Configuration bean definition 'org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration$TokenKeyEndpointRegistrar' 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'.

I have found jira for a very similar problem:

https://jira.spring.io/browse/SPR-14234

but it is marked as closed and should be fixed in 4.2.6.RELEASE.

回答1:

Your problem relates to bean factory post processor initialization by spring.

Ref in documentation: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factory-postprocessors

BeanFactoryPostProcessor interface is used for different enhancements before beans initialization in container.

One of the best examples related to the described problem is PropertySourcesPlaceholderConfigurer. It is bean factory post processor that is used for properties externalization from separate file. Properties in a bean are resolved with help of @Value annotation and syntax "${property.name}".
Ref: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-placeholderconfigurer

So, PropertySourcesPlaceholderConfigurer is the bean factory post processor. It should be initialized before any bean is created in the spring container, otherwise it can't do its job. It should change bean meta-data with correct values from properties files. That is why it should be declared static in configuration class:

@Configuration
public class AppConfig {

     @Bean
     public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
           return new PropertySourcesPlaceholderConfigurer();
     }
}

In java, static fields and methods are loaded the same time as particular class is loaded by the class loader. So, bean factory post processor declaration is available without need to create a bean of the particular holder class. Spring loads bean factory post processor from static method and later creates the bean of the configuration class.

Spring documentation emphasises this point in this paragraph: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-value-annotations

Current behavior is the same as decribed by Juergen Hoeller in the ticket. Spring will print in logs a warning about bean factory post processor declared without static modifier.



回答2:

Maybe this helps (or not)...

@RunWith(SpringRunner.class)
@DataJpaTest
public class TestMyImpl {
...

I'm using 4.3.4.RELEASE and have the following warning for the code block above:

2016-12-30 07:33:04.296 WARN 2000 --- [ main] o.s.c.a.ConfigurationClassPostProcessor : Cannot enhance @Configuration bean definition 'embeddedDataSourceBeanFactoryPostProcessor' 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'.

Since I use @DataJpaTest which autoconfigures the test database (h2 in this case) by replacing any dataSource it finds, the behaviour is expected and wanted. The warning is a confirmation of the overriding behaviour of @DataJpaTest.

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
public class TestMyImpl {
...

By disabling the autoconfiguration (as shown above) the warning disappears. The datasource can now be configured as usual.