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

时间:2011-10-04 17:09:30

标签: jsf glassfish cdi

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

我有一个ViewScoped bean,它通过类似的实用程序类引用服务:

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

@ManagedBean
@ViewScoped
public class UserHandler {
  public String method() {
     ServicesUtil.getUserService().doUserStuff();
     return "newPage";
  }
}

我的问题是,由于ServicesUtil是ApplicationScoped,这是否意味着整个应用程序每个服务只有一个实例?这是不好的做法吗?如果正确完成,GlassFish中的CDI是否会在需要时实际创建新实例?

同样,如果将服务注入UserHandler,那么应用程序是否会更具可扩展性?

我们添加了ServicesUtil层的原因是我的一个同事说他在ViewScope时偶尔会遇到让Handler注入工作的问题。在ViewScoped bean中使用@EJB会有困难吗?

非常感谢任何帮助!

罗布

1 个答案:

答案 0 :(得分:2)

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

根据您使用的EJB类型(无状态,有状态或单例),不同的东西会持有。

如果userService和emailService是无状态的(它们很可能是无状态的),那么通过使用首先注入到应用程序范围的bean中的bean,你什么都得不到。也就是说,注入的不是bean本身而是代理,并且每个请求都被路由到不同的真实bean实例(参见http://en.wikipedia.org/wiki/Enterprise_JavaBean#Stateless_Session_Beans)。

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

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

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

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