如何使用CDI使单例实例在任何地方都可见?

时间:2019-07-12 09:39:08

标签: java rest java-ee singleton cdi

我有一个申请。每个用户对应于实体“客户”。在会话期间,用户使用其实体。

我有JAX-RS + EJB应用程序。我希望此实体作为单个实例可见并在所有服务中使用。我想使用CDI实现它。

首先,用户登录到应用程序。登录后,我想从基础中获取其实体并将其分配给单例,但是我没有成功。我尝试了@Singleton注释(javax.inject),@SessionScoped@ApplicationScoped

我该怎么办?

//Entity
@Entity
@SessionScope //or @Singlton/@ApplicationScope
class Client { fields }

//login service
@Inject 
Client client;
//After login I want to assign an entity from db[cleintEntity] 
//to entity which is available everywhere[client]
client = clientEntity;

我想这样做:

//some ejb
@Inject
Client client;
//use entity

我不想在整个应用程序中传输到实例的链接,但是我希望使用CDI在任何地方都可以使用它。

还是我需要创建一个单独的ClientDAO,它将是我的单身汉?

1 个答案:

答案 0 :(得分:1)

根据您的评论,您必须使用@SessionScope。如果您想为所有用户提供一个实例,可以使用@Singleton@ApplicationScope

要解决您的问题,

  1. 您要在用户登录时实例化Client。因此,当您使用登录服务时,该对象尚未实例化,因此您无法将其@Inject实例化到您的登录服务,您应该记得删除@Inject注释。

  2. 您需要使用@Produces批注。当您希望控制类的实例化方式时,可以使用此注释。当CDI容器想要找到Client类的实现时,如果它找到返回Client并具有@Produces批注的方法,则它会调用该方法,而不仅仅是实例化{{1 }}本身。您应该进行登录业务,然后创建Client的实例并将其作为成员变量存储在登录服务中。然后在此类中添加一个返回该客户端对象的方法,并用Client对该方法进行注释。您的登录服务的最终结构将如下所示:

@Produces

您还可以将 @SessionScope public class LoginService { private Client client; public void login(String username, String password) { // implement login business // if login is successful client = clientEntity; } @Produces @SessionScope public Client clientProducer() { return this.client; } } 批注放在字段顶部。在这种情况下,CDI容器将使用存储在该字段上的值,而不是调用方法。

@Produces

当然,这应该被视为一种伪代码。我不知道您的业务的所有详细信息。也许您实现逻辑的方式是完全错误的;)。但是要解决此特定问题, @SessionScope public class LoginService { @Produces @SessionScope private Client client; public void login(String username, String password) { // implement login business // if login is successful client = clientEntity; } } 应该可以工作。