为什么某些 API(如 JCE、JSSE 等)通过单例映射提供可配置属性?
例如:
Security.setProperty("ocsp.enable", "true");
并且仅在使用 CertPathValidator
时使用。我看到两个导入选项:
- 同样是单例,但每个属性都有 getter 和 setter,
- 一个对象包含与当前上下文相关的属性: (..) (它已经有一个
PKIXParameters
的设置器,这是一个好的开始,但它并不包含所有内容)
一些原因可能是:
CertPathValidator.setValidatorProperties 来自命令行的属性 - 从命令行到上面建议的类中的默认值的简单转换器将是微不足道的,
- 允许不同提供者提供其他自定义属性 - 他们可以拥有
public Map getProviderProperties()
,甚至public Object ..
带强制转换。
我很好奇,因为这些属性并不总是在最明显的地方,并且在使用 API 时无法看到它们,您必须在(如果幸运的话)获得它们之前查看数十个谷歌结果。因为——首先——你并不总是知道你到底在寻找什么。
我刚刚观察到的另一个致命缺点是这不是线程安全的。例如,如果两个线程想要通过 ocsp 检查撤销,它们必须设置 ocsp.responderURL 属性......并且可能覆盖彼此的设置。
For example:
Security.setProperty("ocsp.enable", "true");
And this is used only when a CertPathValidator
is used. I see two options for imporement:
- again singleton, but with getter and setter for each property
- an object containing the properties relevant to the current context:
CertPathValidator.setValidatorProperties(..)
(it already has a setter forPKIXParameters
, which is a good start, but it does not include everything)
Some reasons might be:
- setting the properties from the command line - a simple transformer from command-line to default values in the classes suggested above would be trivial
- allowing additional custom properties by different providers - they can have
public Map getProviderProperties()
, or evenpublic Object ..
with casting.
I'm curious, because these properties are not always in the most visible place, and instead of seeing them while using the API, you have to go though dozens of google results before (if lucky) getting them. Because - in the first place - you don't always know what exactly you are looking for.
Another fatal drawback I just observed is that this is not thread-safe. For example if two threads want to check a revocation via ocsp, they have to set the ocsp.responderURL
property.. and perhaps override the settings of each other.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这实际上是一个很好的问题,迫使您思考过去可能做出的设计决策。感谢您提出一个我几年前就应该想到的问题!
听起来反对意见与其说是单例方面(尽管对此可能会发生完全不同的讨论),不如说是字符串键的使用。
我曾经研究过使用这种方案的 API,并且您上面概述的原因绝对是驱动因素 - 它使解析命令行或属性文件变得非常简单,并且它允许第 3 方可扩展性而不影响官方API。
在我们的库中,我们实际上有一个类,其中每个官方参数都有一堆静态最终字符串条目。这给了我们两全其美的好处——开发人员仍然可以在有意义的地方使用代码完成。还可以使用内部类构建相关设置的层次结构。
尽管如此,我认为第一个原因(命令行的简单解析)并没有真正解决问题。创建一个反射驱动机制将设置推送到一堆设置器中将相当容易,并且它将防止字符串->对象转换的麻烦转移到主应用程序类中。
可扩展性有点棘手,但我认为它仍然可以使用反射驱动系统来处理。这个想法是让主配置对象(其中包含所有设置器的对象)也有一个 registerExtensionConfiguration(xxx) 方法。标准符号(可能是点分隔)可用于深入研究配置对象的结果非循环图,以确定应在何处调用设置器。
上述方法的优点是它将所有命令行参数/属性文件解析异常处理放在一处。不存在格式错误的论点在受到攻击之前会流传数周的风险。
This is actually a great question that forces you to think about design decisions you may have made in the past. Thanks for asking a question that should have occurred to me years ago!
It sounds like the objection is not so much the singleton aspect of this (although an entirely different discussion could occur about that) - but the use of string keys.
I've worked on APIs that used this sort of scheme, and the reasons you outline above were definitely the driving factors - it makes it crazy simple to parse a command line or properties file, and it allows for 3rd party extensibility without impact to the official API.
In our library, we actually had a class with a bunch of static final String entries for each of the official parameters. This gave us the best of both worlds - the developer could still use code completion where it made sense to do so. It also becomes possible to construct hierarchies of related settings using inner classes.
All that said, I think that the first reason (easy parsing of command line) doesn't really cut it. Creating a reflection driven mechanism for pushing settings into a bunch of setters would be fairly easy, and it would prevent the cruft of String->object transformation from drifting into the main application classes.
Extensibility is a bit trickier, but I think it could still be handled using a reflection driven system. The idea would be to have the main configuration object (the one with all the setters in it) also have a registerExtensionConfiguration(xxx) method. A standard notation (probably dot separated) could be used to dive into the resultant acyclic graph of configuration objects to determine where the setter should be called.
The advantage of the above approach is that it puts all of the command line argument/properties file parsing exception handling in one place. There isn't a risk of a mis-formatted argument floating around for weeks before it gets hit.