是否有可能在Java中修补补丁?

ric*_*chq 21 java reflection monkeypatching

我不想讨论这种方法的优点,只要有可能.我相信答案是"不".但也许有人会让我感到惊讶!

想象一下,你有一个核心小部件类.它有一个calculateHeight()返回高度的方法.高度太大 - 这导致按钮(比如说)太大了.您可以扩展DefaultWidget以创建自己的NiceWidget,并实现自己calculateHeight()的返回更好的大小.

现在,一个库类WindowDisplayFactory,在一个相当复杂的方法中实例化DefaultWidget.您希望它使用您的NiceWidget.工厂类的方法看起来像这样:

public IWidget createView(Component parent) {
    DefaultWidget widget = new DefaultWidget(CONSTS.BLUE, CONSTS.SIZE_STUPIDLY);

    // bunch of ifs ...
    SomeOtherWidget bla = new SomeOtherWidget(widget);
    SomeResultWidget result = new SomeResultWidget(parent);
    SomeListener listener = new SomeListener(parent, widget, flags);

    // more widget creation and voodoo here

    return result;
}
Run Code Online (Sandbox Code Playgroud)

这就是交易.结果使DefaultWidget深入其他对象的层次结构中.问题 - 如何让这个工厂方法使用我自己的NiceWidget?或者至少calculateHeight()在那里自己动手.理想情况下,我希望能够修补DefaultWidget,以便其calculateHeight做正确的事情......

public class MyWindowDisplayFactory {
    public IWidget createView(Component parent) {
        DefaultWidget.class.setMethod("calculateHeight", myCalculateHeight);
        return super.createView(parent);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我在Python,Ruby等方面可以做的事情setMethod().虽然我已经发明了这个名字.对我开放的其他选择是:

  • createView()方法的代码复制并粘贴到我自己的继承工厂类的类中
  • 生活在太大的小部件

工厂类无法更改 - 它是核心平台API的一部分.我尝试对返回的结果进行反射以获得(最终)添加的小部件,但它是几个小部件层向下并且在某处它用于初始化其他东西,导致奇怪的副作用.

有任何想法吗?到目前为止,我的解决方案是复制粘贴工作,但这是一个需要在升级到较新版本的平台时跟踪父工厂类中的更改的警察,我有兴趣听到其他选项.

And*_*ndy 9

也许您可以使用面向方面编程来捕获对该函数的调用并返回您自己的版本?

Spring提供了一些AOP功能,但也有其他库也可以.

  • 你不需要Spring来做AOP,只需要获得AspectJ.还有一个eclipse插件:http://www.eclipse.org/aspectj/ (2认同)

Joa*_*uer 7

一个丑陋的解决方案是在类路径上比普通实现更早地放置自己的DefaultWidget实现(使用相同的FQCN).这是一个可怕的黑客,但我能想到的其他方法更糟糕.