我想让Jersey2和Guice一起合作,这显然相当困难。我已经看到了一些涉及使用HK2-to-Guice桥的解决方案。但该桥依赖于在自定义Jersey2 ServiceLocator
的{{1}}中获取HK2 init()
实例以初始化ServletContainer
:
GuiceBrige
但不知何故,在泽西岛(2.26)的最新版本中,public class MyServletContainer extends ServletContainer {
@Override public void init() {
ServiceLocator sloc = getApplicationHandler().getServiceLocator();
...
} }
中getServiceLocator()
不再存在ApplicationHandler
。我怎样才能在这种情况下得到它?
答案 0 :(得分:8)
免责声明:我不使用Guice,所以这不是我测试过的。因此,我不知道OP正在尝试做什么甚至可以工作。我只是回答了如何获取ServiceLocator的主要问题。
正如my comment here中提到的,从2.26开始,泽西岛不再对HK2有 hard 依赖。因此,在整个代码库中,您将不再看到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);
只是底层定位器的高级委托人
super.init()
需要指出的一点是,我的免责声明的主要原因是您需要先在init()
方法中拨打ApplicationHandler
,否则你当你试图获得init()
时会得到一个NPE。这个问题是完成了很多的初始化;几乎整个应用程序都已初始化。因此,尝试添加Guice集成可能会或可能不会太晚。
以下是我见过这种集成的其他地方。而且我相信在ResourceConfig
结尾处尝试这样做之前,他们都会被击中。
InjectionManager
构造函数中,您可以在其中注入Feature
。InjectionManager
中,您可以通过InjectionManagerProvider
静态方法获取ComponentProvider
。AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setView(R.layout.activity_alertdialog_date);
DatePicker datePicker = (DatePicker) findViewById(R.id.Activity_AlertDialog_SetStartDate);
// ... The rest of the AlertDialog, with buttons and all that stuff
alert.create().show()
,如the docs中所述。我见过的唯一一个实现是Spring。您可以在jersey-spring4中查看来源。这可能需要更多工作,但我认为这将是最合适的位置,因为它在所有其他先前选项之前被调用。可能不需要它,因为我已经看到其他人可以选择其他两个选项。答案 1 :(得分:0)
这里有同样的问题。
我最终在全局静态类中注册了从我的 FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job downtimeOverNotificationJob = dispatcher.newJobBuilder()
.setService(AppJobService.class) // the JobService that will be called
.setTag("my-unique-tag") // uniquely identifies the job
.setTrigger(Trigger.executionWindow(20,20))
.build();
dispatcher.mustSchedule(downtimeOverNotificationJob);
@Override
public boolean onStartJob(JobParameters job) {
Toast.makeText(this, "Job started", Toast.LENGTH_SHORT).show();
new Handler(Looper.getMainLooper()).postDelayed(() -> {
//Do something after 10000ms
stopSelf();
}, 5000);
return false; // Answers the question: "Is there still work going on?"
}
@Override
public boolean onStopJob(JobParameters job) {
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Vibrate for 500 milliseconds
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(500,VibrationEffect.DEFAULT_AMPLITUDE));
}else{
//deprecated in API 26
v.vibrate(500);
}
return false; // Answers the question: "Should this job be retried?"
}
子类注入的ServiceLocator,并希望它在正确的时间可用。确实如此,但我不知道使用
javax.ws.rs.core.Application
那样有点整洁。
另一种方法是将InjectionMananger#getInstance(ServiceLocator.class);
实现的类名放在META-INF / services中。这样,您就可以控制整个应用程序的根服务定位器,直到它到达Jersey。这里的问题是必须重写的单个方法必须返回一个新的ServiceLocatorGenerator
对象,但是您不能使用ServiceLocator
创建该对象,因为它会导致无限递归。因此,您必须创建并配置一个ServiceLocatorFactory
,它非常复杂。但是,存在一个ServiceLocatorImpl
,可以简单地从github复制并用作您的实现。您可以在这里将Guice桥接到HK2,然后再进行其他操作。我还没有尝试过,但是很快。