在Java中实现一个提供程序,作为默认提供程序的包装器
JDK里有若干抽象类,它们包含一个名为 provider() 的 static 方法。示例有
SelectorProviderHttpServerProviderAsynchronousChannelProvider
现在设想我们需要对从 SelectorProvider.provider() 获得的默认实例所执行的行为做出一点变动。自然的解决方案是获取它、对其进行包装、进行委托,并在需要时对调用或结果做出轻微修改。
然而似乎没有办法做到这一点,因为正如 SelectorProvider的文档 所说:一旦你已经调用了 .provider(),就会始终返回同一个实例。因此即使你对其进行包装,也无法安装或启用包装器。
但对默认实现进行包装似乎是一个非常自然的做法。我是不是漏掉了一个极其简单的办法?
解决方案
我不确定问题出在哪儿。如果你要的是:“我想要系统范围的提供者,但再对其进行包装以做出一些微小修改”,那么问题在哪儿?只要每次都这么做就行了。如果你要的是:“我想注册一个系统范围的提供者;这枚新创建的提供者我要通过拿系统范围的提供者并增添一堆花哨的功能来打造”,那么:
要修改提供者,只需阅读javadoc。对这两种情形:一方面,了解如何改变系统默认提供者;另一方面,了解如何得到你想要包装的东西。
注意,你的方法有一个根本性的问题:你在试图篡改全局状态。你想修改每一个调用.provider() 的调用方所接收到的内容。
设想系统中有两家库都想做你正在尝试做的事(获取“默认”的提供者,无论那是什么,将其包装以修改某些行为,然后宣布这个包装后的东西为“新默认”)。那这个怎么运作?很可能你希望给其他所有人调用.provider() 的结果等价于 wrapLibA(wrapLibB(actualSystemProvider)),但你如何解决这个你想当然的问题?
这也是你之所以会觉得这件事不那么容易的根本原因,你需要投入一些努力:你必须重现默认行为,或对基础提供者进行硬编码。