如何干净地覆盖Jersey使用的默认ServiceLocator?

我正在开发一个应用程序,它使用Jersey(2.5)作为其REST前端,Jetty作为嵌入式HTTP(S)服务器,两者都采用所谓的“嵌入式”方式,例如。 不依靠制作.war并部署它,而是通过处理程序,资源,注入的程序化配置……

我想以某种方式覆盖Jersey在服务器端使用的HK2 ServiceLocator ,或者可能为父服务定位器提供一个父服务器来解析在应用程序的REST部分之外定义的依赖关系。 从我看到的代码来看,这似乎不可能:ServiceLocator通过调用InjectionsApplicationHandler实例化:

 if (customBinder == null) { this.locator = Injections.createLocator(new ServerBinder(application.getProperties()), new ApplicationBinder()); } else { this.locator = Injections.createLocator(new ServerBinder(application.getProperties()), new ApplicationBinder(), customBinder); } 

注射中的代码告诉我以下内容:

  public static ServiceLocator createLocator(Binder... binders) { return _createLocator(null, null, binders); } 

这意味着新创建的服务定位器具有一些任意生成的名称,并且没有父项。

有没有(干净的)方法来改变这种行为,以便我注入我自己的ServiceLocator作为应用程序的父级?

我知道这个答案有点晚了。 我在同样的问题上挣扎,但在Dropwizard框架中。 经过一些调试,我看到了一些代码让我开心!

 final ServiceLocator locator = (ServiceLocator) webConfig.getServletContext() .getAttribute(ServletProperties.SERVICE_LOCATOR); 

这段代码在jerseyes WebComponent构造器中。 所以解决方案是为ServletContext提供ServletProperties.SERVICE_LOCATOR 。 在Dropwizard环境中,我实现了它

 environment.getApplicationContext().getAttributes().setAttribute(ServletProperties.SERVICE_LOCATOR, locator); 

我们有类似的设置,我已经设法使用jwells131313的新bridgeServiceLocator API来使用我们的架构。

编辑:请注意,当前的HK2桥接实现意味着Singleton实例仅在创建它们的ServiceLocator本地,这意味着桥接体系结构可以包含多个Singleton服务的实例。 请参阅此问题以获取更多信息和可能的解决方法/替代方法。

编辑#2:修复了ServiceLocator桥中的上述错误。 修复程序将在hk2 2.5.0-b07或更高版本中

基本上我创建了一个Feature实现来设置桥接并将其注册到Jersey(在我们的实例中通过ServletContainer )。

 public class InjectionBridge implements Feature { private static ServiceLocator _applicationServiceLocator; private final ServiceLocator _serviceLocator; @Inject private InjectionBridge(ServiceLocator serviceLocator) { _serviceLocator = serviceLocator; } @Override public boolean configure(FeatureContext context) { if (_applicationServiceLocator != null) ExtrasUtilities.bridgeServiceLocator(_serviceLocator, _applicationServiceLocator); return true; } public static void setApplicationServiceLocator(ServiceLocator applicationServiceLocator) { _applicationServiceLocator = applicationServiceLocator; } } 

然后,从应用程序代码调用setApplicationServiceLocator并使用应用程序创建的ServiceLocator来管理应用程序资源。

这意味着Jersey RESTful服务实现现在可以简单地使用@Inject批注声明字段,并访问那些注入资源以服务请求。

在创建ServiceLocator之后,您无法使一个ServiceLocator成为另一个ServiceLocator的父级。

但是,从hk2 2.4.0-b11开始,将能够拥有ServiceLocator – > ServiceLocator桥。 因此,ServiceLocator的所有服务都可以放入Jersey(或任何其他ServiceLocator)的ServiceLocator中。 这是API: bridgeServiceLocator 。 它位于hk2的hk2-extras模块中。

在hk2 2.4.0-b10中有一个版本可以使用,完全测试和记录的function将在hk2 2.4.0-b11