这个JSF模式会破坏依赖注入吗?

这个JSF模式会破坏依赖注入吗?,jsf,glassfish,cdi,Jsf,Glassfish,Cdi,我有一个JSF2项目(GlassFish 3.1上的Mojarra) 我有一个ViewScope bean,它通过如下实用程序类引用服务: @ManagedBean @ApplicationScoped public static class ServicesUtil { @EJB UserService userService; @EJB EmailService emailService; /** getters/setters **/ } 及 我的问题是,既然Serv

我有一个JSF2项目(GlassFish 3.1上的Mojarra)

我有一个ViewScope bean,它通过如下实用程序类引用服务:

@ManagedBean
@ApplicationScoped
public static class ServicesUtil {
  @EJB
  UserService userService;
  @EJB
  EmailService emailService;
  /** getters/setters **/
}

我的问题是,既然ServicesUtil是应用程序范围,那么这是否意味着整个应用程序中每个服务只有一个实例?这是坏习惯吗?如果操作正确,GlassFish中的CDI是否会根据需要创建新实例

类似地,如果将服务注入UserHandler,应用程序是否会更具可伸缩性

我们添加ServicesUtil层的原因是我的一位同事说,在处理程序中使用ViewScope时,他偶尔会遇到让注入工作的问题。在ViewScope bean中使用@EJB是否有困难

非常感谢您的帮助


Rob

您使用的模式似乎没有多大意义。将EJB注入到视图范围的bean中应该没有问题

根据您使用的EJB类型(无状态、有状态或单例),不同的情况会发生

如果userService和emailService是无状态的(它们很可能是无状态的),那么使用首先注入到应用程序范围bean中的bean将一无所获。也就是说,注入的不是bean本身,而是一个代理,每个请求都被路由到不同的真实bean实例(请参阅)

如果userService和emailService是有状态的,那么这里就只有一个实例,但是我非常怀疑您是否需要在应用程序中的每个用户之间共享实际的实例。但是,即使您希望这样,一次也只有一个用户(线程)可以访问有状态bean

如果这些服务是单例的,您可以直接将它们注入到视图范围的bean中。绝对没有理由通过应用程序范围的bean

此外,
ServicesUtil.getUserService()
是一个静态方法,因此使用它来获取注入的服务是脆弱的。如果您想使用它(您不应该,但假设)
ServicesUtil
应该被注入到
UserHandler


然后,您似乎混淆了CDI和JSF托管bean。我同意这是令人困惑的,但它是目前的方式
@ViewScoped
在组合CDI bean中不起作用。从您的代码中不清楚
@ManagedBean
是JSF变体还是JavaEE/CDI变体。在本例中,如果要使用视图范围,则应该是
javax.faces.bean.ManagedBean

您使用的模式似乎没有多大意义。将EJB注入到视图范围的bean中应该没有问题

根据您使用的EJB类型(无状态、有状态或单例),不同的情况会发生

如果userService和emailService是无状态的(它们很可能是无状态的),那么使用首先注入到应用程序范围bean中的bean将一无所获。也就是说,注入的不是bean本身,而是一个代理,每个请求都被路由到不同的真实bean实例(请参阅)

如果userService和emailService是有状态的,那么这里就只有一个实例,但是我非常怀疑您是否需要在应用程序中的每个用户之间共享实际的实例。但是,即使您希望这样,一次也只有一个用户(线程)可以访问有状态bean

如果这些服务是单例的,您可以直接将它们注入到视图范围的bean中。绝对没有理由通过应用程序范围的bean

此外,
ServicesUtil.getUserService()
是一个静态方法,因此使用它来获取注入的服务是脆弱的。如果您想使用它(您不应该,但假设)
ServicesUtil
应该被注入到
UserHandler


然后,您似乎混淆了CDI和JSF托管bean。我同意这是令人困惑的,但它是目前的方式
@ViewScoped
在组合CDI bean中不起作用。从您的代码中不清楚
@ManagedBean
是JSF变体还是JavaEE/CDI变体。在这种情况下,如果您想使用视图范围,它应该是
javax.faces.bean.ManagedBean

Hi--您能否详细说明一下“@ViewScoped不能与met CDI beans组合使用”--我不明白您的意思。我目前正在使用javax.faces.bean.ManagedBean和javax.ejb.ejb注释。再次感谢!他的意思是,当您使用
javax.annotation.ManagedBean
(或
javax.inject.Named
)时,它将不起作用。当前正在查看相同的模式。注入ViewScopedBean会保持ejb引用,并且在服务器死机且会话故障转移到新jvm时会出错(如果HA不重要,则不会有问题)。上面的模式是注入模式和服务定位器模式之间的一个很好的折衷方案,即使用
@EJB
注入到应用程序中,然后从请求/视图范围bean中使用它们。您好--您能详细说明一下这个“@viewscoped不能与met CDI bean组合使用”吗?我不明白您的意思。我目前正在使用javax.faces.bean.ManagedBean和javax.ejb.ejb注释。再次感谢!他的意思是,当您使用
javax.annotation.ManagedBean
(或
javax.inject.Named
)时,它将不起作用。当前正在查看相同的模式。注入ViewScopedBean会保持ejb引用,并且在服务器死机且会话故障转移到新jvm时会出错(如果HA不重要,则不会有问题)。上面的模式是注入和服务定位器模式之间的一个很好的折衷方案,即使用
@EJB
注入到应用程序中,然后从请求/视图范围的bean中使用它们。
@ManagedBean
@ViewScoped
public class UserHandler {
  public String method() {
     ServicesUtil.getUserService().doUserStuff();
     return "newPage";
  }
}