应用范围 bean 中的实用方法

Utility methods in application scoped bean

您认为将所有广泛使用的实用方法放在一个应用程序范围的 bean 中是个好主意吗?

在我正在处理的应用程序的当前实现中,所有实用方法(使用字符串、cookie 进行操作、检查 url、检查用户所在的当前页面等)都放在一个大请求作用域 bean,每个 xhtml 页面都会引用它们。

我找不到关于 Whosebug 的任何信息,如果将实用方法放在应用程序作用域 bean 中的方法是好的还是坏的选择。

为什么我遇到这个想法是需要在范围更广的 bean 中重用这些方法,然后再使用请求范围的 bean(如视图或会话范围的 bean)。如果我错了请纠正我,但你应该始终注入相同或更宽范围的 bean,即你不应该在视图范围内注入请求范围的 bean。

我认为使用应用程序作用域 bean 的实用方法应该是有益的(不会创建任何新对象,将创建一个对象并在所有应用程序中重新使用),但我仍然想要确认或有人告诉我这是否是错误的方法以及为什么是错误的。

至于 bean 范围,如果 bean 没有任何状态(即 class 没有任何可变实例变量),那么它可以安全地处于应用程序范围内。另见 How to choose the right bean scope? 这一切都与 bean 的用途无关(实用性与否)。鉴于实用程序函数根据定义是无状态的,那么您绝对应该使用应用程序范围的 bean。它节省了在每个请求上实例化的成本。

至于在托管 bean 中使用实用方法,从面向对象的角度来看,这是一种糟糕的做法,因为为了从 EL 访问它们,这些方法不能 static 而它们应该是。您不能将它们用作其他正常 Java classes 中的实际实用方法。像 Sonar 这样的静态代码分析器会用一个大红旗标记它们。因此,这是一种反模式。正确的方法是继续使用真正的实用程序 class(public final classprivate Constructor() 仅使用 static 方法)并将所有这些 static 方法注册为 EL 函数在 your.taglib.xml 中如 How to create a custom EL function to invoke a static method?

中所述

至少,当您打算拥有一个 public 可重复使用的库(例如 JSTL fn:xxx(), PrimeFaces p:xxx() or OmniFaces of:xxx(). If you happen to use OmniFaces, then you could, instead of creating a your.taglib.xml file, reference the class in <o:importFunctions> 时,您应该这样做。它会自动将给定类型的所有 public static 方法导出到 EL 函数范围。

<o:importFunctions type="com.example.Utils" var="u" />
...
<x:foo attr="#{u:foo(bean.property)}" />

如果您不使用 OmniFaces,并且这一切都供内部使用,那么我可以想象为每个突然弹出的微小实用函数重做所有 your.taglib.xml 注册样板会变得很烦人。对于这种 "internal usage only" 情况,我可以合理化并原谅滥用应用程序范围的 bean。只有当你开始 externalize/modularize/publicize 它时,你才应该真正将它们注册为 EL 函数,而不是将不良做法暴露给 public。