Groovy Meta Programming

2019-08-27 16:07发布

问题:

I want to override a method definition in Grails. I am trying to use Groovy metaprogramming as the class which I want to override belongs to a framework.

Below is the original class.

class SpringSocialSimpleSignInAdapter implements SignInAdapter {
    private RequestCache requestCache

  SpringSocialSimpleSignInAdapter(RequestCache requestCache) {
     this.requestCache = requestCache;
 }

    String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) {
      SignInUtils.signin localUserId
      extractOriginalUrl request
   }
}

I am trying to override like below

SpringSocialSimpleSignInAdapter.metaClass.signIn = {java.lang.String str, org.springframework.social.connect.Connection conn, org.springframework.web.context.request.NativeWebRequest webreq ->
        println 'coming here....'  // my implementation here
        return 'something'
    }

But for some reason overriding is not hapening. I am not able to figure it out. Any help would be greatly appretiated.

Thanks

回答1:

Yeah, seems like that bug. I don't know your whole scenario, but anyway, here's a small workaround i made:

  1. In your class definition, you don't implement the interface
  2. You create your object and do your metamagic
  3. Use groovy coercion to make it act as the interface and then you can pass it around

Here is a small script i made using JIRA bug to prove it:

interface I {
    def doIt()
}

class T /*implements I*/ {
    def doIt() { true }
}

def t = new T()
assert t.doIt()

t.metaClass.doIt = { -> false }

// here the coercion happens and the assertion works fine
def i = t as I
assert !i.doIt()
assert !t.doIt()

// here the polymorphism happens fine
def iOnlyAcceptInterface(I i) { assert !i.doIt() }
iOnlyAcceptInterface(i)