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

Java 从EJB无状态会话bean调用CDI会话范围的生产者方法,java,jakarta-ee,cdi,Java,Jakarta Ee,Cdi,我想使用@inject@current user跨所有层(即web层、EJB层)注入当前用户。为此,我采用了以下CDI生产者方法: @Named @SessionScoped public class UserController { @Resource SessionContext sessionContext; @EJB UserDao userDao; @Produces @Current public User getCurrentUser() { S

我想使用
@inject@current user
跨所有层(即web层、EJB层)注入当前用户。为此,我采用了以下CDI生产者方法:

@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

因此,即使
@Stateless
的作用域基本上是“应用程序”,在您的“SomeBackendService”中代表
用户的代理仍有可能委托给正确的会话作用域版本

p、 美国


如果层实际上指的是web中的模块和作为EAR一部分的EJB模块,那么它会稍微复杂一点,因为CDI在模块之间并不总是像预期的那样工作(特别是在JBoss as中)。这部分是由于“应用程序”的含义不明确,因此应用程序范围在EAR中。

根据设计,无状态会话bean不应该有状态“User”,它无论如何都是无状态的


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

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

“如果会话bean使用依赖注入,那么容器会在创建bean实例之后,在对bean实例调用任何业务方法之前,注入这些引用。”-第4.3.2节

我也有这种怀疑,我贴了一个问题来解释这种情况

完全忘记了代理。我试过了,效果如预期。谢谢