栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

基于HttpRequest的jersey 2上下文注入,不带单例

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于HttpRequest的jersey 2上下文注入,不带单例

因此,当您实例化资源使其成为单例时,Jersey会尝试在启动时进行所有注入。这意味着尝试访问本质上属于请求范围的任何对象都将失败… 除非
…该对象是 可代理的

泽西岛(Jersey)使某些对象成为代理对象,这是根据设计和规范进行的。例如

HttpHeaders
UriInfo
SecurityContext
,和其他一些上市这里。尽管
HttpServletRequest
未列出,但它也是可替代的对象之一。

可以代理的意思是,不是注入实际的对象(直到有请求才存在),而是注入了代理。在代理上进行调用时,它们将被转发到当前请求中可用的实际对象。您可以尝试打印/记录的类,

HttpServletRequest
然后您会看到该类实际上是
com.sun.proxy.ProxyX
而不是
HttpServletRequestSomeImpl
。这是Java
动态代理工作的魔力。

您当前面临的问题是的注入

Datastore
。它本质上是请求范围的,因为它的创建依赖于请求上下文信息(即标头)。因此,在注入过程中,此调用无法获取
ContainerRequest
您的工厂内部信息

ContainerRequest request = getContainerRequest();

错误消息为“不在请求范围内”,这很合理,因为当我们尝试获取请求时没有请求。

那么我们该如何解决呢?好吧,我们需要使其成为

Datastore
代理。通常,执行此操作的方法是在绑定声明期间进行配置,例如

bindFactory(...).proxy(true).proxyForSameScope(false).to(...);

proxy(true)
方法使其具有可代理性,并
proxyForSameScope(false)
说如果我们尝试注入同一作用域,则它不应是代理,而应是实际实例。

当前配置的一个问题是您将工厂绑定到工厂

bind(TenantDatastoreFactory.class)  .to(TenantDatastoreFactory.class)  .in(Singleton.class);

这对您当前的实现很有用,因为您正试图将工厂注入

TenantDatastoreFactoryProvider
。但是,使代理工作真正需要的是将工厂绑定到实际的工厂
Datastore

bindFactory(TenantDatastoreFactory.class)        .proxy(true)        .proxyForSameScope(false)        .to(Datastore.class)        .in(RequestScoped.class);

因此,现在我们已经取消了工厂的绑定,我们无法注入它。因此,我们只需

Factory
要从
createvalueFactory
方法中返回a的问题。我们不想只返回
TenantDatastoreFactory
实例,因为在
provide
调用方法获取时,我们仍然会遇到相同的问题
Datastore
。为了解决这个问题,我们可以执行以下操作

@Overrideprotected Factory<?> createvalueFactory(Parameter parameter) {     Class<?> paramType = parameter.getRawType();     TenantDatastore annotation = parameter.getAnnotation(TenantDatastore.class);     if (annotation != null && paramType.isAssignableFrom(Datastore.class)) {         return getFactory();     }     return null;}private Factory<Object> getFactory() {    return new Factory<Object>() {        @Context        Datastore datastore;        @Override        public Object provide() { return datastore;        }        @Override        public void dispose(Object t) {}    };}

因此,我们正在

Factory
动态创建一个代理,在其中注入代理
Datastore
。现在,当Jersey尝试注入资源类时,它将注入代理,并且
provide
永远不会在启动时调用该方法。仅当我们尝试
Datastore
在请求期间实际使用时才调用它。

可能同时创建了

TenantDatastoreFactory

匿名
Factory
作为运行时,这似乎是多余的。但这是必需的,以确保
Datastore
可代理并确保
provide()
在启动时永远不会调用该方法。

另一个注意事项是,如果您不需要参数注入,则可以通过删除来简化实现

TenantDatastoreFactoryProvider
。仅对于参数注入才需要。我们需要做的是
InjectionResolver
处理自定义注释,并在工厂创建
Datastore
。该
InjectionResolver
实施将需要改变如下

public class TenantDatastoreInjectionResolver         implements InjectionResolver<TenantDatastore> {    @Inject    @Named(InjectionResolver.SYSTEM_RESOLVER_NAME)    InjectionResolver<Inject> systemInjectionResolver;    @Override    public Object resolve(Injectee injectee, ServiceHandle<?> handle) {        if (Datastore.class == injectee.getRequiredType()) { return systemInjectionResolver.resolve(injectee, handle);        }        return null;    }    @Override    public boolean isConstructorParameterIndicator() { return false; }    @Override    public boolean isMethodParameterIndicator() { return false; }}

然后在活页夹中,取出

TenantDatastoreFactoryProvider

@Overridepublic void configure() {    bindFactory(TenantDatastoreFactory.class) .proxy(true) .proxyForSameScope(false) .to(Datastore.class) .in(RequestScoped.class);    bind(TenantDatastoreInjectionResolver.class) .to(new TypeLiteral<InjectionResolver<TenantDatastore>>() { }) .in(Singleton.class);}

同样,这仅在不需要参数注入的情况下。

也可以看看

  • 使用HK2和Jersey将请求范围对象注入到单例范围对象中


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/498603.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号