5
@Path(value = "/user")
@Stateless
public class UserService {

    @Inject
    private UserManager manager;

    @Path(value = "/create")
    @GET
    @Produces(value = MediaType.TEXT_PLAIN)
    public String doCreate(@QueryParam(value = "name") String name) {
        manager.createUser(name);

        return "OK";
    }
}

这是用户管理器 impl

public class UserManager {

    @PersistenceContext(unitName = "shop")
    private EntityManager em;

    public void createUser(String name) {
        User user = new User();
        user.setName(name);
        // skip some more initializations 
        em.persist(user);
    }
}

问题是如果我没有将 UserService 标记为 @Stateless 那么管理器字段为空

但是如果我标记@Stateless,我可以注入管理器字段,并且应用程序可以正常工作,因为我可以将数据保存到数据库中

只是想知道,这背后的原因是什么?

这是连接应用程序的首选方式吗?

好吧,我正在考虑将 EntityManager 拉出给生产者,以便可以共享

4

2 回答 2

8

问题是,如果我没有将 UserService 标记为 @Stateless,那么 manager 字段为 null

要进行注入,类必须是托管组件,例如 Enterprise Bean、Servlet、过滤器、JSF 托管 bean 等或CDI 托管 bean(这是 Java EE 6 的新部分,您可以将任何类设为托管 bean与 CDI)。

那么,如果您不将 JAX-RS 端点设为 EJB,如何启用注入?这在使用 Glassfish v3的 JAX-RS 和 CDI 集成中得到了很好的解释:

启用 CDI 托管 bean 的方式有两种:

  1. 由 CDI 实例化,由 Jersey 管理生命周期。使用 Jersey 范围注释进行注释, @ManagedBean也可以选择使用 Jersey 范围注释进行注释。

  2. 由 CDI 实例化和管理。使用 CDI 范围注释进行注释,例如@RequestScoped@ManagedBean 不需要)

我还建议检查以下资源。

这是连接应用程序的首选方式吗?

我会说是的。CDI 非常好而且……你不喜欢注射吗?

好吧,我正在考虑将 EntityManager 拉出给生产者,以便可以共享

之间共享什么?为什么?在您的情况下,您应该使用一个EntityManager具有范围为单个事务的生命周期(事务范围的持久性上下文)。换句话说,不要共享它(也不要担心为每个请求打开和关闭它,这不是一个昂贵的操作)。

参考

  • JPA 2.0 规范
    • 第 7.6 节“容器管理的持久性上下文”
    • 第 7.6.1 节“容器管理的事务范围持久性上下文”
    • 第 7.6.2 节“容器管理的扩展持久性上下文”

资源

于 2010-09-19T13:48:41.790 回答
0

@Singleton注释将有所帮助:http ://www.mentby.com/paul-sandoz/jax-rs-on-glassfish-31-ejb-injection.html

于 2013-04-27T14:29:19.133 回答