@Inject不使用组件扫描注入并导致NullPointerException

时间:2014-04-27 16:59:06

标签: java spring dependency-injection

我的应用程序上下文XML很简单:

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

在那个包中,我有我的配置:

package com.depressio.spring

@Configuration
@ComponentScan(basePackages = "com.depressio")
public class DepressioConfiguration
{
    @Inject private ApplicationContext context;
}

com.depressio内,有一个存储库(DAO):

package com.depressio.dao;

@Repository
public class ParameterDAO
{
    public Parameter getParameter(long ID) { ... }
}

...以及注射工作正常的服务(使用parameterDAO时没有NPE):

package com.depressio.resource;

@Service
@Path("/depressio/parameters")
public class ParameterResource
{
    @Inject private ParameterDAO parameterDAO;

    @Path("{id}")
    public Response getParameter(long parameterID)
    {
        return Response.ok(parameterDAO.getParameter(parameterID).legacyFormat()).build();
    }
}

但是,legacyFormat()方法调用会构造另一个对象。在该对象中,我必须注入不同的DAO(尽管也注明了@Repository)。注射不起作用。

所以,我们有原始的Parameter对象:

package com.depressio.domain;

public class Parameter
{
    ...
    public LegacyParameter legacyFormat()
    {
        return new LegacyParameter(this);
    }
}

...以及注射不起作用的LegacyParameter

package com.depressio.domain.legacy;

public class LegacyParameter
{
    @Inject private LegacyDAO legacyDAO;
    ....
    public LegacyParameter(Parameter newParameter)
    {
        // NullPointerException when using the injected legacyDAO.
    }
}

我尝试过一些事情,包括:

  • LegacyParameter使用no-args构造函数,然后调用populate方法,以便在构造对象之前不使用注入的DAO。这没有用。

  • LegacyDAO注入ParameterResource并传入。这有效,但不是理想的,因为我必须将它传递给很多(注射应该有帮助)避免,不?)。它确实证明了LegacyDAO是可以注意的......显然不是LegacyParameter

  • @Service上添加@Component@NamedLegacyParameter注释。所有这些都在我尝试引用注入的legacyDAO的行上结束了NullPointerException。

我错过了什么?

1 个答案:

答案 0 :(得分:0)

正如Sotirios所指出的那样,它不会起作用,因为你创建了一个普通的Java对象,并且没有给Spring提供增强它的机会。 让Spring创建你想要享受Spring&#39;魔法的对象。 (比如设置@Inject依赖项等)。 或者自己创建自己的对象并设置依赖项(yourObject.setDao(dao))。

也就是说,在特殊情况下,您仍然希望动态创建对象。由你自己但依靠Spring为这些对象注入依赖。在这种情况下,您应该明确地调用Spring: LegacyParameter p = new LegacyParameter(...); 。applicationContext.getAutowireCapableBeanFactory()autowireBean(P); 在你的情况下,我认为你真的不需要它。 (如果确实需要这样的话,请参阅此链接inject bean reference into a Quartz job in Spring?。)

另外,我建议简化配置。 为什么你同时使用基于xml和基于java的配置呢?在您的示例中,您只能保留其中一个并具有相同的效果。