加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-14 16:36:21 所属栏目:大数据 来源:网络整理
导读:我正在尝试使用元编程覆盖Java类上的私有方法.代码看起来像这样: // Java classpublic class MyClass{ private ClassOfSomeSort property1; private ClassOfSomeOtherSort property2; public void init(){ property1 = new ClassOfSomeSort(); property2 =
我正在尝试使用元编程覆盖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调用,而不是私有方法.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读