【问题标题】:Spring Java Config using Autowired caused NPESpring Java Config 使用 Autowired 导致 NPE
【发布时间】:2013-03-13 17:29:10
【问题描述】:

我很难理解为什么 Spring Java Config 中使用 @Autowired 的东西不起作用。

首先,我试图在 Java Config 类中移动我的所有 @Autowired 注释。这具有使我的“POJO”回到真正的 POJO 的效果。然后,我不仅可以在 Spring 上下文之外轻松测试它们,还可以轻松轻松地使用模拟对象。

所以我首先尝试了这个:

@Configuration
public class Module3ConfigClass {

    @Autowired
    private Module1Bean1 module1Bean1;

    @Autowired
    private Module2Bean1 module2Bean1;

    @Bean
    public Module3Bean1 module3Bean1() {
        return new Module3Bean1(module1Bean1, module2Bean1);
    }
}

但是,当调用Module3Bean1 构造函数时,传入的 Bean 都为 null。如果您没有遵循我上面编造的命名约定,那么这两个 bean 都将由单独的 Java Config 配置文件创建。另请注意,所有 都已正确连接 - 我知道这一点,因为当 @Autowired 标记位于 Module3Bean1 内的相应私有成员字段上时,一切正常。

FWIW,我尝试在 module3Bean1() 方法中添加 @DependsOn 注释,但结果相同。我想我只是真的很想了解这种行为,它是否正确(我怀疑它是,但为什么)?

最后,我找到了一个可接受的解决方法:

@Configuration
public class Module3ConfigClass {

    @Bean
    @Autowired
    public Module3Bean1 module3Bean1(Module1Bean1 module1Bean1, Module2Bean1 module2Bean1) {
        return new Module3Bean1(module1Bean1, module2Bean1);
    }
}

这对我来说似乎很好,但如果有人愿意对此发表评论,那也将受到欢迎。

【问题讨论】:

  • 在自动装配之前需要创建 Bean。向我们展示这些 bean 在哪里,其他配置。您可能需要 @Import 那个 @Configuration 类。
  • 好吧,它们在上述两种情况下都被正确地自动装配了。首先是当自动装配在工厂(配置)过程之外时,第二个是当它们在所示代码中自动装配时。因此,只需假设这些都是琐碎的 bean,每个都在它们自己的 (at)Configuration 注释类中并正确导入。我只是想知道为什么一些(at)Autowired bean 出现在(at)Configuration 类中,而有些(如上所示)没有。
  • 那么我只能假设所有的bean都是在它们有资格进行注入/自动装配之前创建的。至于您的解决方法,我认为该方法可能会被调用两次,一次用于@Bean 创建,一次用于@Autowired。检查您的日志。
  • 谢谢。您提供的用“@Autowired”注释“@Bean”方法的解决方法也对我有用。我仍然不明白为什么在这种情况下对 java 字段进行自动装配不起作用。

标签: java spring configuration


【解决方案1】:

我想你遇到了和我一样的问题。在我的情况下,问题是无效的 xml 配置。在我的模块 B 中,我的配置如下:

<beans>
      <context:component-scan base-package="com.moduleB"/>
      <import resource="classpath:applicationContext-moduleA.xml"/>
</beans>

在 moduleA 上下文中,我放置了“context:annotation-config”注释。 当我将导入/上下文顺序更改为:

<beans>
      <import resource="classpath:applicationContext-moduleA.xml"/>
      <context:component-scan base-package="com.moduleB"/>
</beans>

配置类属性的自动装配开始工作。

【讨论】:

  • 对不起,我错过了这个回复!这对其他人来说是很好的信息,但是由于我没有 XML 配置并且是纯 Java 配置,所以这并不能回答问题(只是告诉你为什么我不能接受这个作为问题答案!)
【解决方案2】:

我们遇到了同样的问题,并得出结论,错误是因为我们有一个循环依赖关系,其中涉及到 BeanPostProcessor

  • 一个 PropertyPlaceholderConfigurer(一个 BeanPostProcessor)已经被配置为在另一个 bean 的帮助下设置它的 propertiesArray 属性:

    <bean id="globalPropertyPlaceholderConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
        lazy-init="false" depends-on="javaLoggingConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config/host/${env.instance}.properties</value>
                <value>WEB-INF/config/host/${env.instance}.properties</value>
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="true" />
        <property name="propertiesArray" value="#{springPropertyFinder.findProperties()}" />
    </bean>
    
  • 用于设置 propertiesArray 的 springPropertyFinder bean 不是一个 BeanPostProcessor 而是一个“普通”bean,它收集所有 Properties 实例:

    public Properties[] findProperties() {
        Map<String, Properties> propertiesMap = applicationContext.getBeansOfType(Properties.class);
    
        for (String title : propertiesMap.keySet()) {
            PropertiesLoggerUtil.logPropertiesContent(logger, "Springcontext Properties ("+title+")", propertiesMap.get(title));
        }
    
        return propertiesMap.values().toArray(new Properties[propertiesMap.size()]);
    }
    
  • @Configuration 类包含一个属性类型的 bean

所以我们的假设是@Configuration类已经创建,没有经过ConfigurationClassPostProcessor(也是一个BeanPostProcessor)的处理,因为PropertyPlaceholderConfigurer依赖于springPropertyFinder,而springPropertyFinder又依赖于@Configuration类中的properties bean。在这些情况下,可能没有正确设置 BeanPostProcessors 的顺序。

此描述的设置在 XML 中有效,但不适用于 Java 配置。

【讨论】:

  • 这看起来非常相似 - @Autowired 也是一个后处理步骤。在这篇文章发布后的几个月里,我们也能够确认(或者我们认为是)这是一个循环引用问题。我怀疑(尽管没有证据),因为 Autowired 早在(我认为是 2.5)Java Config (3.x) 出现之前就得到了支持,因此嵌套的配置类集隐藏了一个微妙的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-28
  • 1970-01-01
  • 2020-12-16
  • 2022-11-23
  • 2012-04-10
  • 1970-01-01
相关资源
最近更新 更多