【问题标题】:Spring bean definition class name is null when using JavaConfig使用 JavaConfig 时 Spring bean 定义类名为空
【发布时间】:2015-11-13 16:45:26
【问题描述】:

我正在实现 BeanFactoryPostProcessor 并且我正在尝试提取 bean 定义类名:

@Component
public class MyFactory implements BeanFactoryPostProcessor{

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
    for (String name : beanDefinitionNames) {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);

        // 'null' when using JavaConfig, 'java.lang.String' when using XML
        System.out.println(beanDefinition.getBeanClassName());
    }

}

}

当我通过 XML 配置我的 bean 时,我得到类名没有任何问题:

<bean id="arbitraryString" class="java.lang.String"/>

<bean class="com.test.MyFactory"/>

但是,当我使用 JavaConfig 并在那里定义一个 bean(用于演示目的的简单字符串)时,类名将为 null:

@Bean 
public String arbitraryString () {
    return "the bean definition class name will be null";
}

我已尝试搜索此内容,但无法理解我是否做错了什么或这是预期的行为。我在我的主要方法中没有做任何其他事情,而是加载上下文(无论是 XML 还是配置类)。

【问题讨论】:

  • 您是否尝试过在注释中提供 Bean 名称? @Bean(name = "arbitraryString")
  • 可能重复:stackoverflow.com/questions/17155539/… 这似乎是预期的行为
  • @MichaelMurray 刚刚尝试过,仍然为空。
  • @pandaadb 这不是重复的,我确实找到了这个问题,但它没有解决在这种情况下使用 JavaConfig 和 xml 之间的区别。

标签: java spring spring-java-config


【解决方案1】:

我已经研究了一下,我想我知道问题可能是什么(不确定我是否正确,或者我是否解释正确)。但是,这似乎是问题所在:

在你的 JavaConfig 类中定义 bean 会导致这个类在 spring 中初始化。我认为这里的顺序很重要:

它将获取您的配置类,检索所有 @Bean 注释的方法,然后创建这些对象。

现在我相信您所指的“根 bean”是一个实现类,以防您实例化该类。这看起来很自然,但是在 spring XML 和 spring javaconfig 之间有一个限制。

在xml中:

所有 bean 都被定义为类。它们是通过调用该类的构造函数来实例化的。

在 JavaConfig 中:

bean 不再是独立的 bean。它被视为工厂 bean。所以 bean 并没有真正的根 bean 类,它有一个工厂 bean 和一个工厂方法。您将如何从方法定义中设置根类?您可以将根 bean 设置为类,但这在大多数类中不成立。工厂可以返回返回类的任何实现,因此在创建 BeanDefinition 对象时,没有可用的根 bean。

这可以通过将您的 appconfig 标记为静态(工厂方法)来观察。现在,没有工厂 bean,因为在扫描配置类时,它没有被创建。这意味着,spring 将使用 CGI 创建一个作为根 bean 的实现。然而,这不是您所期望的根 bean。例如,在我的测试中:

com.*.*.AppConfig$$EnhancerBySpringCGLIB$$1d5cc574

这是我在创建静态 bean 时得到的输出。

总之:

JavaConfig 就像一个工厂,所以创建的 bean 在定义形成时是未知的。

Xml 定义良好,实现类显式设置,因此给出了根 bean。

需要生成静态bean,因为工厂不存在,但是仍然需要创建类。

希望对你有帮助:)

-- 阿图尔

编辑:最后说明,这是预期的行为:)

【讨论】:

  • 您也可以通过打印配置 bean 来观察这一点。需要通过调用构造函数来创建配置。因此很清楚实现 bean 将是什么,因此(由 CGI 增强的)类是根 bean。在我的例子中: appConfig : Root bean: class [com.*.*.AppConfig$$EnhancerBySpringCGLIB$$1d5cc574]
【解决方案2】:

@Bean 的 Bean 由 ConfigurationClassBeanDefinitionReader 和 bean 定义 定义类为AnnotatedBeanDefinition

所以。你可以从它的FactoryMethodMetadata获取类名

if(beanDefinition instanceof AnnotatedBeanDefinition) { // definition with @Bean Annotation cause this issue
    MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata();
    if (factoryMethodMetadata != null) {
        className = factoryMethodMetadata.getReturnTypeName();
    }
}

【讨论】:

    猜你喜欢
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-21
    • 1970-01-01
    • 2014-02-10
    相关资源
    最近更新 更多