泽西岛和HK2 ServiceLocator

问题描述 投票:2回答:2

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

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

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

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

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

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

locator.Create(AWorker.class) 

注入它。

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

jersey hk2
2个回答
3
投票

你是如何启动你的容器的?如果您使用的是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)。


1
投票

我将假设您正在启动一个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;
    }
© www.soinside.com 2019 - 2024. All rights reserved.