我想在所有层(即Web层,EJB层)上使用@Inject @Current User
注入当前用户。为此,我有以下CDI Producer方法:
@Named
@SessionScoped
public class UserController {
@Resource SessionContext sessionContext;
@EJB UserDao userDao;
@Produces @Current
public User getCurrentUser() {
String username = sessionContext.getCallerPrincipal().getName();
User user = userDao.findByUsername(username);
}
}
@Qualifier
@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface Current{}
现在,我想将当前用户注入EJB无状态会话bean,如下所示:
@Stateless
public class SomeBackendService {
@Inject @Current
private User user;
}
我的问题:当前用户对象是否总是在会话更改后重新注入,因为无状态会话bean的依赖关系通常在创建时注入一次,并且bean可能被池化并在不同的会话中使用?
答案 0 :(得分:4)
虽然我没有尝试过这种确切的情况,但通常不会重新注入CDI bean。相反,注入了一个知道其上下文的代理。
通过这种机制,可以在应用程序范围的bean中注入一个会话范围的bean。应用程序作用域bean的每个用户都转到同一个bean和相同的代理,但是代理将动态地将对它的调用解析为每个用户的不同bean。
因此,即使@Stateless
的范围基本上是“应用程序”,但是在“SomeBackendService”中代表User
的代理仍然可以委托给正确的会话范围版本。
P.S。
如果使用 layers ,你实际上意味着模块在Web和EJB模块中属于EAR的一部分,它会变得有点复杂,因为CDI并不总是按预期工作模块(特别是在JBoss AS中)。这部分是由于“应用程序”的含义模糊,因此应用程序范围在EAR中。
答案 1 :(得分:1)
按照设计,你的无状态会话bean不应该有一个状态“User”,它无论如何都是无状态的。
如果您希望EJB具有状态,请改用@Stateful。
答案 2 :(得分:1)
是的,对于称为容器的每个业务方法,将重新注入SLSB的所有依赖项。这是在EJB 3.1规范中保证这一点的文本:
“如果会话bean使用依赖注入,容器会在创建bean实例之后,以及在bean实例上调用任何业务方法之前注入这些引用。” - 第4.3.2节
我也有这个疑问,我发布了一个解释这种情况的问题 here