我有一个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会有困难吗?
非常感谢任何帮助!
罗布
答案 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
。