@Inject和@Autowired没有工作,而注入setter工作

时间:2014-12-27 04:36:56

标签: java spring dependency-injection

我使用@Autowired数百次,但今天我没有得到它,@Autowired@Inject都没有在我刚创建的新项目中工作,我得到了一个着名的错误

  

无效的属性' jdbcTemplate' bean类[com.xxx.SomeDAO]:Bean   property' jdbcTemplate'不可写或具有无效的setter   方法。 setter的参数类型是否与getter的返回类型匹配?

当我在jdbcTemplate中为SomeDAO添加setter时,它可以正常工作......

的applicationContext.xml:

...
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="com.xxx.SomeDAO" class="com.xxx.SomeDAO">
    <property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
...

SomeDAO.java:

import org.springframework.jdbc.core.JdbcTemplate;
import javax.inject.Inject;
//import org.springframework.beans.factory.annotation.Autowired;

public class SomeDAO {

    @Inject // Doesn't work
    //@Autowired // Doesn't work either
    private JdbcTemplate jdbcTemplate;
    ...

    /* Works if I add this setter
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }*/
}

什么可以通过注释阻止注入?谢谢!

1 个答案:

答案 0 :(得分:1)

当使用XML-context以您提供的方式创建bean时,无法使用字段注入。您的类不是任何组件扫描的一部分,因此注释不起作用。因此,我至少可以看到以下选项:

<强> 1。根据您的示例使用setter,然后移除@Inject

这是最简单的方法,因为您已准备好代码和XML。但是,这意味着您的DAO必须公开不必要的setter方法。

<强> 2。使用设置jdbcTemplate字段

的构造函数

根据我的说法,这是一个更好的选择,但这意味着您需要像这样重写XML:

<bean id="com.xxx.SomeDAO" class="com.xxx.SomeDAO">
    <constructor-arg ref="jdbcTemplate"/>
</bean> 

而且,你的构造函数是这样的:

public class SomeDAO {
    private final JdbcTemplate jdbcTemplate;

    public SomeDAO(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

第3。添加组件扫描并使用@Autowired(或@Inject)

我认为如果您完全想要利用Spring的依赖注入功能,这是最好的方法。将以下内容添加到XML上下文中:

<context:component-scan base-package="com.xxx"/>

然后您之前提供的代码应该可以使用。但是,您应该考虑避免使用场注入来支持构造函数注入。 opinions differ on this matter但我发现使用场注入时代码更难测试。

构造函数注入如下所示:

// The component scanner will find this annotation and create 
// the bean (and inject the dependencies)
@Component
public class SomeDAO {
    private final JdbcTemplate jdbcTemplate;

    @Autowired // enables constructor-injection
    public SomeDAO(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

我个人更喜欢备选#3,因为它是干净的,基于Java的(几乎不需要XML),这也意味着重构友好,没有字段 magic 发生和基于构造函数的方法使代码可测试,并且不暴露任何不必要的setter方法。

了解更多相关信息的一个很好的起点是优秀Spring Documentation。在那里你可以找到所有上述的一个很好的解释!