如何在 Jersey2 ServletContainer 中获取 HK2 ServiceLocator?
How to get HK2 ServiceLocator in a Jersey2 ServletContainer?
我想让Jersey2和Guice一起合作,这显然是比较困难的。我已经看到一些涉及使用 HK2-to-Guice 桥的解决方案。但是桥依赖于在自定义 Jersey2 ServletContainer
的 init()
中获取 HK2 ServiceLocator
实例来初始化 GuiceBrige
:
public class MyServletContainer extends ServletContainer {
@Override public void init() {
ServiceLocator sloc = getApplicationHandler().getServiceLocator();
...
} }
但不知何故,在最新版本的 Jersey (2.26) 中,getServiceLocator()
不再存在于 ApplicationHandler
中。在这种情况下我怎样才能得到它?
免责声明:我不使用 Guice,所以这不是我测试过的东西。所以我不知道 OP 试图做的事情是否会奏效。我只是简单回答如何获取ServiceLocator的主要问题。
如 所述,从 2.26 开始,Jersey 不再 hard 依赖 HK2。因此,在其整个代码库中,您将不再看到对 ServiceLocator
的引用,而是更高级别的 InjectionManager
。 InjectionManager
与 ServiceLocator
具有相同的目的,但抽象允许依赖注入提供程序的不同实现。这就是为什么在使用 2.26 时,我们需要添加 jersey-hk2
依赖。这是 InjectionManager
的 HK2 实现。在此实现中,InjectionManager
将在适当的情况下简单地将调用委托给底层 ServiceLocator
。
也就是说,ApplicationHandler
现在让您可以访问 InjectionManager
,而不是 ServiceLocator
。 ServiceLocator
本身就是一个服务,所以如果你有一个定位器,你可以执行以下操作(这是没有意义的,但它只是说明了我的观点)
ServiceLocator locator = getServiceLocator();
locator = locator.getService(ServiceLocator.class);
这意味着您还可以从InjectionManager
获取定位器,它只是底层定位器的高级委托
InjectionManager im = getApplicationHandler().getInjectionManager();
ServiceLocator locator = im.getInstance(ServiceLocator.class);
需要指出一件事,我免责声明的主要原因是您需要在 init()
中调用 super.init()
first方法,否则当您尝试获取 ApplicationHandler
时,您将获得 NPE。问题在于完成了很多的初始化;几乎整个应用程序都已初始化。因此,尝试添加您的 Guice 集成可能为时已晚,也可能不会太晚。
以下是我在其他一些地方看到此集成完成的地方。而且我相信在 init()
.
结束时你尝试这样做之前他们都会被击中
- 在
ResourceConfig
构造函数中,您可以在其中注入 InjectionManager
.
- 在
Feature
中,您可以通过 InjectionManagerProvider
静态方法获取 InjectionManager
。
- 我还没有看到这个的任何实现,但我认为做桥的首选位置是
ComponentProvider
,如 the docs. The only implementation I have seen is for Spring. You can see the source in the jersey-spring4 中所述。这可能需要更多的工作,但我认为这将是最合适的位置,因为它在所有其他先前选项之前被调用。不过,这可能不是必需的,因为我看到其他人选择了其他两个选项。
同样的问题。
我最终在全局静态 class 中注册了 ServiceLocator——我从我的 javax.ws.rs.core.Application
subclass 注入的,并希望它在正确的时间可用.它确实有效,但我不知道我可以通过使用
来达到同样的效果
InjectionMananger#getInstance(ServiceLocator.class);
这样比较整洁。
另一种方法是将 class 实现 ServiceLocatorGenerator
的名称放在 META-INF/services 中。这将使您在整个应用程序到达 Jersey 之前控制根服务定位器。这里的问题是必须重写的单一方法必须 return 一个新的 ServiceLocator
对象,但是你不能使用 ServiceLocatorFactory
来创建这个对象,因为它会导致无限递归。因此,您必须创建和配置一个非常复杂的 ServiceLocatorImpl
。但是,ServiceLocatorGeneratorImpl
存在,可以简单地从 github 复制并用作您的实现。在发生任何其他事情之前,您可以在此处将 Guice 桥接到 HK2。我还没有尝试过,但很快就会尝试。
我想让Jersey2和Guice一起合作,这显然是比较困难的。我已经看到一些涉及使用 HK2-to-Guice 桥的解决方案。但是桥依赖于在自定义 Jersey2 ServletContainer
的 init()
中获取 HK2 ServiceLocator
实例来初始化 GuiceBrige
:
public class MyServletContainer extends ServletContainer {
@Override public void init() {
ServiceLocator sloc = getApplicationHandler().getServiceLocator();
...
} }
但不知何故,在最新版本的 Jersey (2.26) 中,getServiceLocator()
不再存在于 ApplicationHandler
中。在这种情况下我怎样才能得到它?
免责声明:我不使用 Guice,所以这不是我测试过的东西。所以我不知道 OP 试图做的事情是否会奏效。我只是简单回答如何获取ServiceLocator的主要问题。
如 ServiceLocator
的引用,而是更高级别的 InjectionManager
。 InjectionManager
与 ServiceLocator
具有相同的目的,但抽象允许依赖注入提供程序的不同实现。这就是为什么在使用 2.26 时,我们需要添加 jersey-hk2
依赖。这是 InjectionManager
的 HK2 实现。在此实现中,InjectionManager
将在适当的情况下简单地将调用委托给底层 ServiceLocator
。
也就是说,ApplicationHandler
现在让您可以访问 InjectionManager
,而不是 ServiceLocator
。 ServiceLocator
本身就是一个服务,所以如果你有一个定位器,你可以执行以下操作(这是没有意义的,但它只是说明了我的观点)
ServiceLocator locator = getServiceLocator();
locator = locator.getService(ServiceLocator.class);
这意味着您还可以从InjectionManager
获取定位器,它只是底层定位器的高级委托
InjectionManager im = getApplicationHandler().getInjectionManager();
ServiceLocator locator = im.getInstance(ServiceLocator.class);
需要指出一件事,我免责声明的主要原因是您需要在 init()
中调用 super.init()
first方法,否则当您尝试获取 ApplicationHandler
时,您将获得 NPE。问题在于完成了很多的初始化;几乎整个应用程序都已初始化。因此,尝试添加您的 Guice 集成可能为时已晚,也可能不会太晚。
以下是我在其他一些地方看到此集成完成的地方。而且我相信在 init()
.
- 在
ResourceConfig
构造函数中,您可以在其中注入InjectionManager
. - 在
Feature
中,您可以通过InjectionManagerProvider
静态方法获取InjectionManager
。 - 我还没有看到这个的任何实现,但我认为做桥的首选位置是
ComponentProvider
,如 the docs. The only implementation I have seen is for Spring. You can see the source in the jersey-spring4 中所述。这可能需要更多的工作,但我认为这将是最合适的位置,因为它在所有其他先前选项之前被调用。不过,这可能不是必需的,因为我看到其他人选择了其他两个选项。
同样的问题。
我最终在全局静态 class 中注册了 ServiceLocator——我从我的 javax.ws.rs.core.Application
subclass 注入的,并希望它在正确的时间可用.它确实有效,但我不知道我可以通过使用
InjectionMananger#getInstance(ServiceLocator.class);
这样比较整洁。
另一种方法是将 class 实现 ServiceLocatorGenerator
的名称放在 META-INF/services 中。这将使您在整个应用程序到达 Jersey 之前控制根服务定位器。这里的问题是必须重写的单一方法必须 return 一个新的 ServiceLocator
对象,但是你不能使用 ServiceLocatorFactory
来创建这个对象,因为它会导致无限递归。因此,您必须创建和配置一个非常复杂的 ServiceLocatorImpl
。但是,ServiceLocatorGeneratorImpl
存在,可以简单地从 github 复制并用作您的实现。在发生任何其他事情之前,您可以在此处将 Guice 桥接到 HK2。我还没有尝试过,但很快就会尝试。