当前位置: 首页 > 知识库问答 >
问题:

JavaGuice DI错误:未满足DependencyException:没有对象可用于注入在SystemInject teeImpl

楚宪
2023-03-14

我有一个使用Jersey 2.x的简单REST API项目。我尝试使用GoogleGuice注入我的依赖项,但似乎不起作用。我得到这个错误:

组织.glassfish.hk2.api.不满意的依赖性例外:在系统导入过程中没有可用于注入的对象(必填类型=帐户服务,父=帐户资源,限定符={},位置=0,可选=假,自=假,非限定=空,1658198405)

我有这个简单的资源类

@Path("/accounts")
@Produces(MediaType.APPLICATION_JSON)

public class AccountsResource {

    private final AccountService accountService;

    @Inject
    public AccountsResource(AccountService accountService) {
        this.accountService = accountService;
    }

  @GET
  @Path("test")
  public String test() {
    return this.accountService.test();
  }

我想将此服务注入我的资源类

public class AccountService {

    public AccountService() {}

    public String test() {
        return "test";
    }
}

因此,按照Guice的指南,我创建了这个模块类

import com.google.inject.*;

public class AccountsResourceModule extends AbstractModule  {

@Override
protected void configure() {
    bind(AccountService.class);
}
}

最后,我在我的主方法中添加了注入器

public class TradingServer implements Runnable {
private static final int PORT = 8181;

public static void main(String[] args) {
    Injector injector = Guice.createInjector(new AccountsResourceModule());
    AccountsResource accountsResource = injector.getInstance(AccountsResource.class);
    new TradingServer().run();
}

public void run() {
    Server server = new Server(PORT);
    ServletContextHandler contextHandler = new ServletContextHandler(server, "/");
    ResourceConfig packageConfig = new ResourceConfig().packages("ca.ulaval.glo4002.trading");
    ServletContainer container = new ServletContainer(packageConfig);
    ServletHolder servletHolder = new ServletHolder(container);

    contextHandler.addServlet(servletHolder, "/*");

    try {
        server.start();
        server.join();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        server.destroy();
    }
}

}

当我调用我的服务器时,我得到了上面提到的错误。看起来依赖注入没有起作用。请帮帮忙

共有1个答案

曹嘉许
2023-03-14

所以泽西对吉斯一无所知。它已经使用了自己的DI框架HK2。您可以做几件事。您可以将 Guice 与 HK2 绑定在一起,以便 HK2 可以找到绑定在 Guice 内部的服务,或者另一种方法是将资源类绑定到 Guice 内部,并将这些资源的实例注册到 Jersey。

要将Guice与HK2联系起来,您需要使用Guice HK2桥。首先,您需要添加以下依赖项

<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>guice-bridge</artifactId>
    <version>${hk2.version}</version>
</dependency>

要获得< code>hk2.version,请查看您的球衣依赖项(您可以运行< code>mvn dependency:tree并查看hk2球衣的版本)。您需要确保您使用的是完全相同的版本。

接下来您需要做的是以编程方式链接这两个系统。一种方法是在< code >功能中。

public class GuiceFeature implements Feature {

    @Override
    public boolean configure(FeatureContext context) {
        // This is the way in Jersey 2.26+ to get the ServiceLocator.
        // In earlier versions, use
        // ServiceLocatorProvider.getServiceLocator(context);
        ServiceLocator locator = InjectionManagerProvider.getInjectionManager(context)
                .getInstance(ServiceLocator.class);

        Injector injector = Guice.createInjector(new AccountResourceModule());
        GuiceBridge.getGuiceBridge().initializeGuiceBridge(locator);
        GuiceIntoHK2Bridge guiceBridge = locator.getService(GuiceIntoHK2Bridge.class);
        guiceBridge.bridgeGuiceInjector(injector);
        return true;
    }
}

然后,只需在泽西岛注册该功能即可。

ResourceConfig packageConfig = new ResourceConfig()
        .packages("ca.ulaval.glo4002.trading")
        .register(GuiceFeature.class);

仅此而已。我已经测试过了,它应该可以工作。

通过上述配置,泽西将创建资源类的实例(@Path注释类)。我们需要桥接的原因是泽西与HK2紧密耦合,因此当我们注入资源类时,在创建实例时,泽西将调用HK2尝试查找资源的所有依赖项。

不过在这种情况下,我们不会依赖Jersey来创建资源的实例。我们将资源绑定到Guice,并让Guice在我们请求时创建实例。我们将使用该实例向Jersey注册。

首先绑定资源

public class AccountResourceModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(AccountService.class);
        bind(AccountResource.class);
    }
}

还要确保资源类中的@Inject注释是com.google.Inject.Inject

获取资源实例并注册它

Injector injector = Guice.createInjector(new AccountResourceModule());
AccountResource accountResource = injector.getInstance(AccountResource.class);

ResourceConfig config = new ResourceConfig()
        .register(accountResource);

你可能需要找出一种更干净的方法来做这件事,因为你不想对你拥有的每一种资源都这样做。但如果你需要做什么,这就是要点。

这里有一个快速实现来清理第二个解决方案。我们能做的是递归地扫描一个包,获取所有的< code>@Path注释类,然后将它们绑定在Guice中,并向Jersey注册。

从这篇SO文章中,我们可以使用反射库轻松获取所有类。只需添加以下依赖项

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.11</version>
</dependency>

然后制作一个小助手类

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.Path;
import org.reflections.Reflections;

public class ResourceClassHelper {

    private static Set<Class<?>> resourceClasses;

    public static Set<Class<?>> getResourceClasses() {
        if (resourceClasses != null) {
            return resourceClasses;
        }

        // the package to scan for @Path classes "com.example"
        Reflections reflections = new Reflections("com.example");

        resourceClasses = reflections.getTypesAnnotatedWith(Path.class);
        resourceClasses = Collections.unmodifiableSet(resourceClasses);
        return resourceClasses;
    }
}

然后在Guice模块中

public class AccountResourceModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(AccountService.class);

        ResourceClassHelper.getResourceClasses().forEach(this::bind);
    }
}

和您的资源注册

Injector injector = Guice.createInjector(new AccountResourceModule());

ResourceConfig config = new ResourceConfig();
ResourceClassHelper.getResourceClasses()
            .forEach(cls -> config.register(injector.getInstance(cls)));
 类似资料:
  • UnsatifiedDependencyException:创建名为'org.springframework.boot.autoConfigure.orm.jpa.HibernateJPAAutoConfiguration'的bean时出错:通过构造函数参数0表示的不满足的依赖关系;嵌套异常是org.springframework.beans.factory.beanCreationExcepti

  • 在Jersey Rest应用程序中使用DI时出现错误: 我对这个概念很陌生,它似乎很复杂,因为有一些例子似乎被弃用了。据我所知,有几种方法可以使DI工作:原生HK2,Spring/ HK2桥。什么更容易配置,更直接?如何以编程方式(不是XML的粉丝)为泽西岛2.x设置? 资源配置 摘要确认器 定价资源 定价服务 更新 更新3: JUnit输出: 调试时: 是对象, 已将所有字段。 更新4: 添加到

  • 为什么我会得到不满意的链接错误? 细节如下: 本机方法的原型及其在我的Java代码中的调用是这样的: 私有本机long sampleFunction(long[][]twoDimArray,long number); p.SampleFunction(twoDimArray,number); 本机方法在VC++代码中的原型是这样的: JNIEXPORT jlong JNICALL Java_MyC

  • 我正在尝试创建一个带有Wildfly和数据库连接的EJB Web项目,以持久化我的类“article”。但当我启动我的应用程序时,我得到了错误 包装服务; ArticleDaoImpl

  • 我是一名学生,正在为我的学校项目开发OCR功能。到目前为止,我能够成功地实现这些功能并运行应用程序。 我在Android Studio1.5.1上有我的应用程序,并且能够在我的旧设备三星银河笔记3应用编程接口21上运行它。最近,我将我的设备更改为三星银河笔记5应用编程接口22,每当我试图运行光学字符识别功能时,应用程序就会崩溃。 以下是日志: 致命异常:java。lang.IllegalState

  • 我正在尝试使用JNLP构建一个小程序。我编写了一个Ant脚本来编译java类、构建jar文件并对它们进行签名。我使用与Ant构建的相同的密钥库对所有jar进行了签名。我在Java控制面板中授予了显示自签名小程序的权限。如果我直接运行JNLP文件,一切都很好,但是如果我将此小程序放在网页中,我会得到不满意的LinkError。 这是我得到的错误: 我根据操作系统构建的每个jar文件都包含gluege