【问题标题】:Optionally inject ContainerRequestContext可选择注入 ContainerRequestContext
【发布时间】:2014-12-18 16:18:23
【问题描述】:

在我的 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,这将大大简化我的代码,有什么想法可以做到这一点吗?

【问题讨论】:

    标签: java dependency-injection jersey hk2


    【解决方案1】:

    我已经找到了一种方法,但这基本上是一种 hack。您可以尝试从ServiceLocator 显式获取ContainerRequestContext 实例,而不是注入ContainerRequestContext,并在上下文超出请求范围时处理异常。

    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;
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      处理可选注入的简单方法是将@Inject插入javax.enterprise.inject.Instance&lt;T&gt;,然后在instance.get()之前调用instance.isUnsatisfied()

      【讨论】:

        猜你喜欢
        • 2017-10-24
        • 2015-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-23
        • 1970-01-01
        相关资源
        最近更新 更多