本文介绍了您可以使用 Groovy 元编程来覆盖 Java 类上的私有方法吗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用元编程覆盖 Java 类上的私有方法.代码如下所示:

I'm trying to override a private method on a Java class using meta programming. The code looks something like this:

// Java class
public class MyClass{

    private ClassOfSomeSort property1;
    private ClassOfSomeOtherSort property2;

    public void init(){

        property1 = new ClassOfSomeSort();
        property2 = new ClassOfSomeOtherSort();

        doSomethingCrazyExpensive();
    }

    private void doSomethingCrazyExpensive(){
        System.out.println("I'm doing something crazy expensive");
    }
}

// Groovy class
public class MyClassTest extends Specification{

    def "MyClass instance gets initialised correctly"(){

        given:
        ExpandoMetaClass emc = new ExpandoMetaClass( MyClass, false )
        emc.doSomethingCrazyExpensive = { println "Nothing to see here..." }
        emc.initialize()
        def proxy = new groovy.util.Proxy().wrap( new MyClass() )
        proxy.setMetaClass( emc )
        when:
        proxy.init()
        then:
        proxy.property1 != null
        proxy.property2 != null
    }
}

问题是没有调用 doSomethingCrazyExpensive 的重写实现 - 我认为这是因为私有方法是由 init() 方法在内部调用的,而不是通过元类调用的.如果我直接调用 myProxy.doSomethingCrazyExpensive(),则会调用覆盖的方法,因此元编程在某种程度上确实起作用.

The problem is that the overridden implementation of doSomethingCrazyExpensive isn't called - I think that this is because the private method is called by the init() method internally and not called through the metaClass. If I call myProxy.doSomethingCrazyExpensive() directly, the overridden method is invoked, so the meta-programming does work to some degree.

有没有一种方法可以使用元编程来覆盖 Java 类(或实例)上的方法,以便在内部调用时调用被覆盖的实现?

Is there a way to use meta programming to override a method on a Java class (or instance) in such a way that the overridden implementation is called when it is invoked internally?

推荐答案

Groovy as 运算符非常强大,可以从在 Java 中可见其更改的具体类型创建代理.可悲的是,虽然我设法更改了公共方法,但它似乎无法覆盖私有方法:

Groovy as operator is quite powerful, and can create proxies out of concrete types whose changes are visible in Java. Sadly, seems like it can't override private methods, though i managed to change a public method:

Java 类:

public class MyClass{

    public void init(){
        echo();
        doSomethingCrazyExpensive();
    }

    public void echo() { System.out.println("echo"); }

    private void doSomethingCrazyExpensive(){
        System.out.println("I'm doing something crazy expensive");
    }
}

常规测试:

class MyClassTest extends GroovyTestCase {
    void "test MyClass instance gets initialised correctly"(){

        def mock = [
          doSomethingCrazyExpensive: { println 'proxy crazy' },
          echo: { println 'proxy echo' }
        ] as MyClass

        mock.init()

        mock.doSomethingCrazyExpensive()
    }
}

它打印:

proxy echo
I'm doing something crazy expensive
proxy crazy

所以公共方法被拦截和改变,即使是从 Java 调用,但不是私有方法.

So the public method got intercepted and changed, even when being called from Java, but not the private one.

这篇关于您可以使用 Groovy 元编程来覆盖 Java 类上的私有方法吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 04:22