【问题标题】:Why do classes in javax.mail store system properties in static fields? [closed]为什么 javax.mail 中的类将系统属性存储在静态字段中? [关闭]
【发布时间】:2020-07-13 11:17:30
【问题描述】:

我在javax.mail 中遇到了problem handling file names,其中一些方面需要通过会话属性和一些系统属性进行配置。 javax.mail 的许多类似乎将它们处理的属性存储在静态字段中,例如以下 MimeBodyPart 的示例:

private static final boolean encodeFileName =
PropUtil.getBooleanSystemProperty("mail.mime.encodefilename", false);

据我了解,这将系统属性的具体值绑定到某个具体类加载器中的类的生命周期。谁首先加载该类,谁是唯一能够影响该值的人。这正是发生在我身上的事情:

我知道我需要设置一些特定的系统属性来影响文件名处理,并在我处理文件名的地方这样做,以使事物尽可能靠近以用于文档等目的。但由于某种原因,加载了以前的代码之前感兴趣的类,将错误的值绑定到静态字段。改变这一点的唯一方法是将我的值设置到调用层次结构中更早的位置,但我花了一些时间才注意到静态字段的事情。

这对我来说似乎是一个糟糕的策略,因为我无法轻易知道与我共享同一个类加载器的哪些代码使用了我所做的相同类。从理论上讲,这将迫使我在已经启动 JVM 时设置我的系统属性,使我的代码的实现细节成为各种不同情况下的管理细节。如果完全使用系统属性而不是 session-once,我希望这些属性会像 session-once 一样被实时查询。否则在某些情况和用例下更改相应的设置是不必要的困难。

OTOH,目前的方法可能只是有一些我不知道的好处,比如查询系统属性非常昂贵。

那么,MimeBodyPart 进行上述操作的充分理由是什么?

【问题讨论】:

  • 坦率地说,javax.mail 有更多的缺陷。除了糟糕的设计,我真的想不出其他原因。
  • 这是整个 Java 的标准做法。它不仅限于 JavaMail。

标签: java jakarta-mail system-properties


【解决方案1】:

据我了解,这将系统属性的具体值绑定到某个具体类加载器中的类的生命周期。谁首先加载该类,谁是唯一能够影响该值的人。这正是发生在我身上的事情。

在命令行上设置属性要安全得多,但是,我理解您拒绝这样做。根据您的问题,暗示您正在使用 java.lang.System::setProperty 设置属性。正如您将在文档中看到的那样,这样做有一些可怕的警告。

根据 API 文档:

API 说明: 除非另有说明,否则更改标准系统属性可能会产生不可预知的结果。有关详细信息,请参阅 getProperties。

java.lang.System::getProperties

API 注意:除非另有说明,否则更改标准系统属性可能会产生不可预知的结果。 属性值可能会在初始化期间或首次使用时被缓存。在初始化之后使用 getProperties()、setProperties(Properties)、setProperty(String, String) 或 clearProperty(String) 设置标准属性可能不会达到预期的效果。

The Java™ Tutorials -> System Utilities -> System Properties

警告:更改系统属性具有潜在危险,应谨慎行事。许多系统属性在启动后不会重新读取,它们仅供参考。更改某些属性可能会产生意想不到的副作用。

简而言之,如果您希望它始终正确设置,则必须使用命令行。

【讨论】:

  • javax.mail 的属性是否完全是那些“标准属性”,或者该文本与路径分隔符、用户名和其他类型的东西不相关吗?除此之外,特别是对于javax.mail,在命令行上设置东西在应用服务器这样的环境中根本不安全,这些环境有许多不同的应用程序,可能有许多不同的需求。根据需要在每个应用程序运行时进行设置是正确的做法,而不是与其他应用程序冲突。当一个应用在不同情况下需要不同的设置时,就会出现问题。
  • @ThorstenSchöning 正确。对于这种情况,getProperties 中的适用行是最后一句。粗体的使用只是从文档中复制的。我回答的重点是过度关注您问题中令人惊讶的行为方面的部分。 JavaMail/JakartaMail 符合现有的 System.property 行为。
【解决方案2】:

你说得对,@maio290,它是故意设计得很差的。 :-)

在多线程应用程序中,动态查询属性并没有真正的帮助。

在大多数情况下,这些静态属性不会在应用程序的生命周期内发生变化。

在某些情况下,使用静态是一种不幸的妥协,因为需要它的代码无权访问会话。更改所有 API 以显式传递 Session 会使代码更加复杂。

考虑了线程本地存储,但这在很大程度上取决于应用程序使用的线程模型。

尽可能使用 Session 属性,但在某些情况下没有好的方法可以做到这一点,因此使用了 System 属性。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
相关资源
最近更新 更多