如何使用 CDI 使单例实例随处可见?
How to make an singleton instance visible everywhere using CDI?
我有申请。每个用户对应实体"Client"。在会话期间,用户使用他的实体。
我有 JAX-RS + EJB 应用程序。我希望这个实体在所有服务中都可见并作为一个单例使用。我想用CDI来实现。
首先,用户登录到应用程序。登录后,我想从base中获取它的entity,并赋值给一个singleton,但是没有成功。我尝试了 @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
我不想在整个应用程序中将 link 传输到实例,但我希望它在使用 CDI 的任何地方都可用。
或者我是否需要创建一个单独的 ClientDAO
,这将是我的单身人士?
根据您的评论,您必须使用 @SessionScope
。如果您想为所有用户使用一个实例,则可以使用 @Singleton
和 @ApplicationScope
。
解决您的问题:
你想在用户登录时实例化Client
。所以当你在登录服务时,这个对象还没有实例化,所以你不能@Inject
它进入您的登录服务,您应该记得删除 @Inject
注释。
您需要使用@Produces
注解。当您想控制实例化 class 的方式时使用此注释。当 CDI 容器要查找 Client
class 的实现时,如果它找到 returns Client
并且具有 @Produces
注释的方法,它会调用该方法而不是仅仅实例化 Client
本身。你应该做你的登录业务,然后创建一个 Client
的实例并将它作为成员变量存储在你的登录服务中。然后在这个class which returns that client object中添加一个方法,并用@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;
}
}
您还可以将 @Produces
注释放在字段顶部。在这种情况下,CDI 容器将使用存储在该字段上的值而不是调用方法。
@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;
}
}
当然这应该被认为是一种伪代码。我不知道你们公司的所有细节。也许您实现逻辑的方式是完全错误的;)。但是要解决这个具体问题,@Produces
应该可以。
我有申请。每个用户对应实体"Client"。在会话期间,用户使用他的实体。
我有 JAX-RS + EJB 应用程序。我希望这个实体在所有服务中都可见并作为一个单例使用。我想用CDI来实现。
首先,用户登录到应用程序。登录后,我想从base中获取它的entity,并赋值给一个singleton,但是没有成功。我尝试了 @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
我不想在整个应用程序中将 link 传输到实例,但我希望它在使用 CDI 的任何地方都可用。
或者我是否需要创建一个单独的 ClientDAO
,这将是我的单身人士?
根据您的评论,您必须使用 @SessionScope
。如果您想为所有用户使用一个实例,则可以使用 @Singleton
和 @ApplicationScope
。
解决您的问题:
你想在用户登录时实例化
Client
。所以当你在登录服务时,这个对象还没有实例化,所以你不能@Inject
它进入您的登录服务,您应该记得删除@Inject
注释。您需要使用
@Produces
注解。当您想控制实例化 class 的方式时使用此注释。当 CDI 容器要查找Client
class 的实现时,如果它找到 returnsClient
并且具有@Produces
注释的方法,它会调用该方法而不是仅仅实例化Client
本身。你应该做你的登录业务,然后创建一个Client
的实例并将它作为成员变量存储在你的登录服务中。然后在这个class which returns that client object中添加一个方法,并用@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;
}
}
您还可以将 @Produces
注释放在字段顶部。在这种情况下,CDI 容器将使用存储在该字段上的值而不是调用方法。
@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;
}
}
当然这应该被认为是一种伪代码。我不知道你们公司的所有细节。也许您实现逻辑的方式是完全错误的;)。但是要解决这个具体问题,@Produces
应该可以。