我的 Web 应用程序中有大量的 Java Bean 类,我正在尝试找到一种在这些 bean 中实现 toString()
方法的简单方法。toString()
方法将用于整个应用程序的日志记录,并且应打印 Bean 中所有属性的属性-值对。
我正在尝试两种选择:
1. BeanUtils.describe()
(Apache commons-beanutils(
2. ReflectionToStringBuilder.toString()
(Apache commons-lang(
由于这是一个预期具有高流量的 Web 应用程序,因此实现必须是轻量级的,并且不应影响性能。(内存使用、处理器使用等是主要考虑因素(。
我想知道根据上述标准,其中哪一个表现更好。据我所知,反思是一项繁重的操作,但对这两种选项的更多详细信息和洞察力将有助于我选择最佳解决方案。
我们在对象的toString()
方法中使用ToStringBuilder.reflectionToString()
。我们在生产环境中运行时没有遇到任何问题。当然,我们很少使用toString()
方法。
我们也使用 BeanUtils.describe()
,但用于其他目的。 BeanUtils
使用PropertyUtilsBean
,它保留了已对其执行内省的 bean 的内部缓存。这似乎会给它带来优于另一个的性能优势,但是在 reflectionToString 源代码中有点闲逛,似乎因为它最终依赖于 java.lang.Class
的实现,缓存也在那里发挥作用。
两者都看起来是一个可行的选择,但BeanUtils.describe()
将返回属性映射,其中 reflectionToString 将返回格式化的字符串。我想这取决于你想用输出做什么。
我建议,如果您的应用程序严重依赖于对对象调用toString()
,那么拥有特定的实现可能会更有益。
就我个人而言,我更喜欢使用 Eclipse/IntelliJ 生成 toString(( 方法,然后根据需要对其进行修改(仅包含重要字段(。
右键单击 -> 源 -> 生成到字符串((。 选择字段。 做。
- 它甚至比编写构建器代码花费的时间更少。
- 它将执行得更快。
- 它不使用permgen空间(反射往往会吞噬permgen(
如果你关心性能,这就是我会走的路。
请注意,因为这是基于反射的,所以会很慢。
在最近的一个 Web 项目中,我们的基本实体 toString(( 方法是 ToStringBuilder.reflectionToString(this(
此方法在保存期间在休眠中调用(通过 Spring Data JPA 存储库(。我们有一个相当大的对象树,其中包含嵌套列表,导致在保存期间内存和 CPU 受到很大影响。
它几乎击沉了这个项目。
只需在 IDE 中使用代码生成器即可生成 toString(( 方法。这样,您将避免因使用反射而造成的开销。在实际生产系统中,可以经常调用 toString(( 方法(100/秒(,导致垃圾回收器努力工作并暂停 JVM。这些暂停可以是几秒钟或几十秒。