使用Autowired的Spring Java Config导致了NPE

时间:2013-03-13 17:29:10

标签: java spring configuration

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

首先,我试图在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构造函数时,在Beans中传递的都是null。如果您没有遵循我上面提到的命名约定,那么这两个bean都将由单独的Java Config配置文件创建。另请注意, 的所有内容都已正确连接 - 我知道这一点,因为当@Autowired标记位于Module3Bean1内的相应私有成员字段时,一切正常。

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

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

@Configuration
public class Module3ConfigClass {

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

这对我来说似乎很好,但如果有人愿意评论它,那也是受欢迎的。

2 个答案:

答案 0 :(得分: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>

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

答案 1 :(得分:0)

我们遇到了同样的问题并得出结论,错误的产生是因为我们有一个循环依赖,其中涉及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而是一个&#34; normal&#34;使用以下函数收集所有Properties实例的bean:

    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类包含Properties
  • 类型的bean

所以我们的假设是@Configuration类是在没有被ConfigurationClassPostProcessor(也是BeanPostProcessor)处理的情况下创建的,因为PropertyPlaceholderConfigurer依赖于springPropertyFinder,它依赖于@Configuration类中的属性bean。在这些情况下,BeanPostProcessors的顺序可能无法正确设置。

这个描述的设置工作在XML中,但不适用于Java配置。