您是否可以使用Groovy元编程来覆盖Java类上的私有方法

我正在尝试使用元编程覆盖Java类上的私有方法.代码看起来像这样:

// 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()方法调用而不是通过metaClass调用.如果我直接调用myProxy.doSomethingCrazyExpensive(),则会调用重写的方法,因此元编程在某种程度上起作用.

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

解决方法

Groovy as operator非常强大,可以使用Java中可见的具体类型创建代理.可悲的是,似乎它无法覆盖私有方法,虽然我设法改变了一个公共方法:

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");
    }
}

Groovy测试:

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调用,而不是私有方法.

相关文章

背景:    8月29日,凌晨4点左右,某服务告警,其中一个...
https://support.smartbear.comeadyapi/docs/soapui/steps/g...
有几个选项可用于执行自定义JMeter脚本并扩展基线JMeter功能...
Scala和Java为静态语言,Groovy为动态语言Scala:函数式编程,...
出处:https://www.jianshu.com/p/ce6f8a1f66f4一、一些内部...
在运行groovy的junit方法时,报了这个错误:java.lang.Excep...