我想@Inject @Current User在所有层(即web层,EJB层)中使用当前用户.为此,我有以下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{}
Run Code Online (Sandbox Code Playgroud)
现在,我想将当前用户注入EJB无状态会话bean,如下所示:
@Stateless
public class SomeBackendService {
@Inject @Current
private User user;
}
Run Code Online (Sandbox Code Playgroud)
我的问题:当前用户对象是否总是在会话更改后重新注入,因为无状态会话bean的依赖关系通常在创建时注入一次,并且bean可能被池化并在不同的会话中使用?
虽然我还没有尝试过这种确切的情况,但在 CDI 中,bean 通常不会重新注入。相反,注入了一个了解其上下文的代理。
通过这种机制,可以在应用程序范围的 bean 中注入会话范围的 bean。应用程序作用域 bean 的每个用户都会使用相同的 bean 和相同的代理,但代理将动态地将对其的调用解析为每个用户的不同 bean。
因此,即使范围@Stateless基本上是“应用程序”,“SomeBackendService”中表示的代理仍然可能User委托给正确的会话范围版本。
附注
如果对于层,您实际上指的是作为 EAR 一部分的 Web 和 EJB 模块中的模块,那么情况会稍微复杂一些,因为 CDI 并不总是按预期在模块之间工作(尤其是在 JBoss AS 中)。部分原因是“应用程序”的含义不明确,因此应用程序范围属于 EAR 之内。