【问题标题】:Jersey and HK2 ServiceLocator泽西岛和 HK2 服务定位器
【发布时间】:2014-01-15 22:01:09
【问题描述】:

我正在尝试在 Application 构造函数(从 ResourceConfig 继承的东西)中初始化我的 Jersey 应用程序中的一些组件。看起来是这样的

public Application(@Context ServletContext context,
                   @Context ServiceLocator locator)...

当我尝试在任何时候使用定位器时,我仍然无法使用 locator.create(MyThing.class) 方法创建已在 AbstractBinder 中注册的事物的实例。

我确定它们已正确绑定,因为它们已通过 @inject 字段注释正确注入到我的资源类中。

不同之处在于 Jersey/HK2 框架正在实例化我的资源类(正如预期的那样,因为它们在我的包扫描路径中),但我似乎无法通过代码利用 ServiceLocator。

我的最终目标是在具有@Inject 属性时注入其他非球衣类,例如。我有一个需要注入配置的数据库访问层的工作类。我想说

locator.Create(AWorker.class) 

然后注入。

如何获得真正的 ServiceLocator,它将注入我已经注册/绑定到我的 Binder 的所有内容? (或者我应该使用 ServiceLocator 以外的东西吗?)

【问题讨论】:

  • 我认为你不能在Application中充分利用hk2。该应用程序提供有关如何设置泽西岛的信息。它还应该告知您与泽西岛相关的 hk2 活页夹。只要没有发生这种绑定,它就不能通过服务定位器获得。
  • 在尝试访问定位器之前,我正在注册我的活页夹。仍然不确定我应该做什么=D
  • 你确定binder不仅注册了,还绑定了它的实例?
  • 我不明白这个问题,但我的活页夹在 configure() 方法中确实 bind(Concrete.Class).to(Interface.class)
  • 使用 locator.create 不需要被创建的东西已经在 HK2 注册。它将尝试继续并创建给定类的实例。此外,MyThing.class 不会由 HK2 管理,因此不能用于进一步注入其他事物。如果类“MyThing.class”使用构造函数注入,那么构造函数所需的服务当然需要在 ServiceLocator 中找到。也许您应该发布从 locator.create(MyThing.class) 获得的异常以及可能是 MyThing.class 代码的相关部分

标签: jersey hk2


【解决方案1】:

你是如何启动你的容器的?如果您使用的是 ApplicationHandler,您只需调用:handler.getServiceLocator()。 ServiceLocator 确实是您想要用来访问依赖项的工具。

如果您正在启动一个 servlet,我发现访问服务定位器的最佳方法是在我的启动类中设置 Jersey 功能:

    private static final class LocatorSetFeature implements Feature {

    private final ServiceLocator scopedLocator;

    @Inject
    private LocatorSetFeature(ServiceLocator scopedLocator) {
        this.scopedLocator = scopedLocator;
    }

    @Override
    public boolean configure(FeatureContext context) {
        locator = this.scopedLocator; // this would set our member locator variable
        return true;
    }
}

该功能只需使用 config.register(new LocatorSetFeature()) 注册到我们的资源配置中。

根据容器的生命周期绑定其他组件的启动很重要,所以这仍然感觉有点hacky。您可以考虑将这些类作为第一类依赖项添加到 HK2 容器中,然后简单地将适当的依赖项注入到您的第三方类中(例如,使用 Binder)。

【讨论】:

  • 您包含的代码无法编译:locator = scopedLocator 无法编译,因为尚未定义定位器,这个变量在哪里?请提供更正。
【解决方案2】:

我将假设您正在启动一个 servlet 并有一个扩展 org.glassfish.jersey.server.ResourceConfig 的类,并且您的绑定已正确注册(例如,使用 Binder 和 registerInstances)。如果您想访问 ServiceLocator 以执行额外的初始化,您有两种选择:

一种方法是注册一个 ContainerLifecycleListener(见此处in this post):

// In Application extends ResourceConfig constructor
register(new ContainerLifecycleListener() {

        @Override
        public void onStartup(final Container container) {
            // access the ServiceLocator here
            final ServiceLocator serviceLocator = container.getApplicationHandler().getInjectionManager().getInstance(ServiceLocator.class);

            // Perform whatever with serviceLocator
        }

        @Override
        public void onReload(final Container container) {
            /* ... */}

        @Override
        public void onShutdown(final Container container) {
            /* ... */}
    });

第二种方法是使用Feature,也可以使用@Provider自动发现:

@Provider
public final class StartupListener implements Feature {

    private final ServiceLocator sl;

    @Inject
    public ProvisionStartupListener(final ServiceLocator sl) {
        this.sl = sl;
    }

    @Override
    public boolean configure(final FeatureContext context) {
        // Perform whatever action with serviceLocator
        return true;
    }

【讨论】:

    猜你喜欢
    • 2015-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多