Cannot enhance @Configuration bean definition 'xxx' * since its singleton instance has been create_Brucelwl的博客-CSDN博客

`项目启动过程中,控制台打印了如下日志
"Cannot enhance @Configuration bean definition 'xxx' 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'."`

意思是: 无法增强@Configuration注解得名字为xxx的bean,原因是这个类被实例化太早了,最常见的原因就是在配置类中使用@Bean标记了一个BeanDefinitionRegistryPostProcessor接口的实现类.考虑使用static去修改这个方法。

1 、本人并没有像警告信息里说的那样在一个配置类中使用@Bean去注入`BeanDefinitionRegistryPostProcessor的实现类,但是导致抛出这个警告的原因是一样的.
先看代码复现下该警告,只需要如下代码即可:`

@Configurationpublic class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { public MyBeanDefinitionRegistryPostProcessor() {   System.out.println();}@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {   System.out.println();} @Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {   System.out.println();  }}

运行结果如下:

通过日志可以看出,该信息在org.springframework.context.annotation.ConfigurationClassPostProcessor中打印,下面来看一下为什么会打印这个警告?

首先ConfigurationClassPostProcessor 实现了接口BeanFactoryPostProcessor, 并在方法postProcessBeanFactory中对所有的@Configuration类进行cglib增强,动态生成配置类的子类,在实例化配置类时是通过子类创建的Bean实例.
full config就是被@Configuration注解标记的配置类, 但是如果配置类在增强之前就被调用getBean()实例化了,就会打印我们所看到的警告信息. 

那么我们的MyBeanDefinitionRegistryPostProcessor为什么会在增强之前被实例化呢? 

原因就在于其实现了接口BeanDefinitionRegistryPostProcessor,该接口是BeanFactoryPostProcessor的子类,当调用org.springframework.context.support.AbstractApplicationContext refresh()方法时会调用invokeBeanFactoryPostProcessors()而该方法中会优先通过getBeanNamesForType() 找到所有的BeanDefinitionRegistryPostProcessor实现类并通过getBean创建bean实例,并遍历调用接口方法postProcessBeanDefinitionRegistry, 其优先于父类接口BeanFactoryPostProcessor得实例执行, 而@Configuration配置类的增强是在BeanFactoryPostProcessor的实现类ConfigurationClassPostProcessor的postProcessBeanFactory方法中执行的,这就导致了MyBeanDefinitionRegistryPostProcessor被提前实例化了, 所以出现了我们所看到的警告信息.
       这个警告信息一般情况下不影响我们的程序运行,当我们仅需要使用的BeanDefinitionRegistryPostProcessor实现类,不需要复杂的配置信息时,可以通过使用@component注解来替换@Configuration.

2、警告中所说的考虑使用static修饰方法是什么情况呢?如下代码其实也会导致出现我们看到的警告信息

@Configurationpublic class MyConfig {     public MyConfig() {        System.out.println();    }     @Bean    public BeanDefinitionRegistryPostProcessor myBeanDefRegPostProcessor() {        return new MyBeanDefinitionRegistryPostProcessor();    }    // 使用static方法则不会打印警告   // @Bean    // public static BeanDefinitionRegistryPostProcessor myBeanDefRegPostProcessor() {    //     return new MyBeanDefinitionRegistryPostProcessor();    // }}

原因是当获取BeanDefinitionRegistryPostProcessor接口的bean时,会调用myBeanDefRegPostProcessor()方法创建Bean,而调用该方法前同样需要先实例化MyConfig,导致了MyConfig在被增强之前被实例化了, 而如果把方法修饰为static,static方法属于类方法,就不会触发MyConfig被提前实例化也就不会出现警告信息了.


原网址: 访问
创建于: 2020-11-25 15:56:09
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论