可选择注入ContainerRequestContext

时间:2014-12-18 16:18:24

标签: java dependency-injection jersey hk2

在我的Jersey应用程序中,我希望将ContainerRequestContext实例注入到各种对象中。如果在请求的上下文之外创建对象,我希望null被注入。

我注意到HK2有一个@Optional注释,您可以用它来注释依赖项,我希望能够完成这项工作,不幸的是它根本不会改变行为。

public class MyObject {

    private final ContainerRequestContext containerRequestContext;

    @Inject
    public MyObject(@Optional ContainerRequestContext containerRequestContext) {
        this.containerRequestContext = containerRequestContext;
    }

}

如果在请求范围之外实例化此对象(在我的情况下,由Quartz调度程序运行作业),则会抛出类似这样的异常:

java.lang.IllegalStateException: Not inside a request scope.

如果Jersey在请求范围之外只注入null,它会大规模简化我的代码,任何想法如何做到这一点?

2 个答案:

答案 0 :(得分:1)

我已经找到了一种方法,但它基本上是一种黑客攻击。您可以尝试从ContainerRequestContext显式获取ContainerRequestContext实例,而不是注入ServiceLocator,并在上下文位于请求范围之外时处理异常。

public class MyObject {

    private final Optional<ContainerRequestContext> containerRequestContext;

    @Inject
    public MyObject(ServiceLocator serviceLocator) {
        this.containerRequestContext = getContainerRequestContext(serviceLocator);
    }

    private Optional<ContainerRequestContext> getContainerRequestContext(ServiceLocator serviceLocator) {
        try {
            return Optional.of(serviceLocator.getService(ContainerRequestContext.class));
        } catch (MultiException e) {
            if (e.getCause() instanceof IllegalStateException) {
                return Optional.empty();
            } else {
                throw new ExceptionInInitializerError(e);
            }
        }
    }
}

然后可以更进一步,创建自己的OptionalContainerRequestContext类型。

public class OptionalContainerRequestContext {

    private final Optional<ContainerRequestContext> containerRequestContext;

    @Inject
    public OptionalContainerRequestContext(ServiceLocator serviceLocator) {
        this.containerRequestContext = getContainerRequestContext(serviceLocator);
    }

    public ContainerRequestContext get() {
        return containerRequestContext.get();
    }

    public boolean isPresent() {
        return containerRequestContext.isPresent();
    }

    private Optional<ContainerRequestContext> getContainerRequestContext(ServiceLocator serviceLocator) {
        try {
            return Optional.of(serviceLocator.getService(ContainerRequestContext.class));
        } catch (MultiException e) {
            if (e.getCause() instanceof IllegalStateException) {
                return Optional.empty();
            } else {
                throw new ExceptionInInitializerError(e);
            }
        }
    }
}

然后你可以绑定它:

bind(OptionalContainerRequestContext.class).to(OptionalContainerRequestContext.class);

然后将其注入您需要的任何地方:

public class MyObject {

    private final OptionalContainerRequestContext optionalContainerRequestContext;

    @Inject
    public MyObject(OptionalContainerRequestContext optionalContainerRequestContext) {
        this.optionalContainerRequestContext = optionalContainerRequestContext;
    }

}

答案 1 :(得分:1)

处理可选注入的简单方法是@Inject进入javax.enterprise.inject.Instance<T>,然后在instance.isUnsatisfied()之前调用instance.get()