栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > 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号