【问题标题】:Inject a singleton bean into a request scoped JAX-RS resource将单例 bean 注入到请求范围的 JAX-RS 资源中
【发布时间】:2014-08-04 01:49:20
【问题描述】:

我正在尝试将 Singleton bean 注入到我的请求范围的 JAX-RS 资源中。我注意到的是,我的 Singleton 的构造函数在每个请求上都会被调用,这显然不是我们想要的行为。我的代码工件如下:-

JAX-RS 资源

@Path("/thing")
@ManagedBean
public class ThingResource {

    //This is desired to be Singleton
    @Inject
    @RedisThingDb
    private ThingDb thingDb;

    //This is request scoped
    @Inject
    private MyRequestScopedObj obj;

    @GET
    @Path("/{id}")
    @Produces("application/json")
    public Thing getById(@PathParam("id") String thingId) {
        return thingDb.findById(thingId);
    }
}

@RedisThingDb 将其标记为单例的注解

@Qualifier
@Singleton
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER     })
public @interface RedisThingDb {

}

创建 RedisDb 对象的生产者代码。

@Produces
@RedisThingDb
public ThingDb getRedisDb() {
    return new RedisDb();// This should be called once, because @RedisThingDb is singleton.
}

RedisDb

public class RedisDb implements ThingDb {
    public RedisDb() {
    logger.debug("Constructing...");
    }

    public Thing findById(Long id){
     ...
    }
}

来自 pom.xml 的依赖(实现为 Wildfly 容器)

    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>

我正在使用 javax.annotation.ManagedBean (@ManagedBean) 注释将 JAX-RS 转换为 CDI 托管 bean。 @RedisThingDb 注解被标记为@Singleton。 JAX-RS 资源是请求范围的,并且有其他请求范围的 bean 注入其中。

【问题讨论】:

  • 您能指定您使用的 JAX-RS/Java EE 版本吗?
  • @JohnAment 我的 maven 依赖如下:- javaxjavaee-api7​​.0提供 我在 WildFly 上运行
  • @JohnAment 抱歉无法弄清楚如何正确格式化我的评论。我正在使用 javax.javaee-api 7.0 范围提供并在 Wildfly 应用程序容器上
  • 非常感谢。您也可以在问题中发布您的beans.xml 吗?

标签: java jakarta-ee singleton jax-rs cdi


【解决方案1】:

我发现您的代码存在两个问题。一方面,您使用@RedisThingDB 作为@Stereotype,但它没有注释@Stereotype。你也应该放弃上面的@Qualifier

其次,更多的是建议,您应该使用范围注释您的端点。 RESTEasy 将为您添加一个范围,@RequestScoped

第三,构造函数被多次调用是完全可以的。真正需要注意的是,如果您的 @PostConstruct 方法被重复调用。由于 CDI 使用代理,构造函数被调用。如果这仍然没有帮助 - 尝试使用 @ApplicationScoped 而不是 @Singleton

【讨论】:

    【解决方案2】:

    【讨论】:

    • 不要在非 GUI 对象上使用@Named
    • 为什么? '@Named' 用于一般用途,例如,与 Spring 中的 '@Component' 相同。
    • 还有一个 javax.annotation.ManagedBean。
    • 就像 JSF ManagedBean) stackoverflow.com/questions/4347374/…
    • 作用域被认为比 CDI 中的任何东西都更“定义 bean”。大多数 JAX-RS 运行时在资源类上看到 @RequestScoped@ApplicationScoped 时将支持注入。
    猜你喜欢
    • 2015-05-05
    • 1970-01-01
    • 2017-12-09
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多