从EJB无状态会话bean调用CDI会话范围的生产者方法

我想在所有层(即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可能被池化并在不同的会话中使用?

虽然我没有尝试过这种确切的情况 ,但通常不会重新注入CDI bean。 相反,注入了一个知道其上下文的代理。

通过这种机制,可以在应用程序范围的bean中注入一个会话范围的bean。 应用程序作用域bean的每个用户都转到同一个bean和相同的代理,但代理将动态地将对它的调用解析为每个用户的不同bean。

因此,即使@Stateless的范围基本上是“应用程序”,但在“SomeBackendService”中代表User的代理仍然可以委托给正确的会话范围版本。

PS

如果使用实际上意味着模块在Web和EJB模块中属于EAR的一部分,那么它会变得有点复杂,因为CDI并不总是在模块之间按预期工作(特别是在JBoss AS中)。 这部分是由于“应用程序”的含义模糊,因此应用程序范围在EAR中。

按照设计,你的无状态会话bean不应该有一个状态“User”,它一定是无状态的。

如果您希望EJB具有状态,请改用@Stateful。

是的,对于称为容器的每个业务方法,将重新注入SLSB的所有依赖项。 这是在EJB 3.1规范中保证这一点的文本:

“如果会话bean使用dependency injection,容器会在创建bean实例之后,以及在bean实例上调用任何业务方法之前注入这些引用。” – 第4.3.2节

我也有这个疑问,我在这里发布了一个解释这种情况的问题