Groovy探索之MOP 十一 運行期內覆蓋invokeMethod

來源:互聯網
上載者:User

 Groovy探索之MOP 十一 運行期內覆蓋invokeMethod

 

 

 

       我們很早就會使用Groovy語言的hook,即"invokeMethod"方法和其他的幾個方法。我們會在一個類中實現"invokeMethod"方法,用來指派所有的或部分的在運行期內調用的該類執行個體的方法。這些我們在《Groovy探索之MOP 一 invokeMethod和methodMissing方法》已經詳細的談到過。

現在,我們已經深入的接觸到了Groovy語言的MetaClass,更是也到處使用到了ExpandoMetaClass。我們都已經知道,ExpandoMetaClass的靈活性,不是hook能夠比擬的。我們就想,既然使用ExpandoMetaClass能夠在運行期內給一個類增加方法,那麼,我們是否也可以在運行期內增加hook方法呢?

我們可以回答,是。還是先來看一個簡單的例子吧!

我們還是有這麼一個簡單的類:

 

class Foo

{

    def foo()

    {

       'foo'

    }

   

 

}

 

我們現在嘗試著在運行期內增加"invokeMethod"方法:

     

      Foo.metaClass.invokeMethod = {

             String name,args1 ->

              'test'

              

      }

 

接著,我們來測試這個運行期內增加的"invokeMethod"方法:

 

      def foo = new Foo()

     

      println foo.foo()

     

      println foo.test()

   

 

運行結果為:

test

test

 

 

可以看出,我們在運行期內增加的"invokeMethod"方法攔截了Foo類的執行個體的所有的方法。

當然,如果我們想把"invokeMethod"方法攔截的方法中,已經存在於Foo類的方法,如"foo",交給Foo類本身的方法來處理。那麼,我們就可以如下實現"invokeMethod"方法:

 

      Foo.metaClass.invokeMethod = {

             String name,args1 ->

               def m = Foo.metaClass.getMetaMethod(name,args1)

               def result

               if(m)

                   result = m.invoke(delegate,args1)

               else

                   result = 'test'

               result

 

      }

 

 

我們再運行上面的測試代碼,就會得到如下的結果:

foo

test

 

現在,我們來定義幾個名詞,我們把類本身實現的"invokeMethod"方法稱為對象的"invokeMethod"方法,而把在運行期內通過ExpandoMetaClass增加的"invokeMethod"方法稱為metaClass的"invokeMethod"方法。

現在的問題是,如果一個對象,同時實行了對象的"invokeMethod"方法和metaClass的"invokeMethod"方法,那麼該調用誰?

你肯定會說,這個問題很簡單啊,我們來做一個簡單的測試不就知道了。好,現在,我們先來看看這個簡單的測試。

首先,我們把上面的Foo類增加"invokeMethod"方法:

 

class Foo

{

    def foo()

    {

       'foo'

    }

   

    def invokeMethod(String name,args)

    {

       'invoke'  

    }

 

}

 

 

同時,我們在運行期內也增加該方法,然後做測試:

 

      Foo.metaClass.invokeMethod = {

             String name,args1 ->

               def m = Foo.metaClass.getMetaMethod(name,args1)

               def result

               if(m)

                   result = m.invoke(delegate,args1)

               else

                   result = 'test'

               result

 

      }

     

      def foo = new Foo()

     

      println foo.foo()

     

      println foo.test()

   

 

啟動並執行結果為:

foo

test

 

 

從結果可以看出,metaClass的"invokeMethod"方法覆蓋了對象的"invokeMethod"方法。即如果存在metaClass的"invokeMethod"方法,則優先調用metaClass的"invokeMethod"方法,而不管對象的"invokeMethod"方法是否存在。

最後,我們還定義一個名詞:GroovyInterceptable的"invokeMethod"方法。這個名詞其實我們在《Groovy探索之MOP 一 invokeMethod和methodMissing方法》也接觸過,就是一個類如果實現了"GroovyInterceptable"介面,那麼它的類本身的"invokeMethod"方法,就是GroovyInterceptable的"invokeMethod"方法。如下所示:

 

class Foo implements GroovyInterceptable{

 

    def foo()

    {

       'foo'

    }

   

    def invokeMethod(String name,args)

    {

       'invoke'  

    }

 

}

 

現在,我們需要知道,如果一個對象的GroovyInterceptable的"invokeMethod"方法和metaClass的"invokeMethod"方法都存在,那麼又是如何調用的?

還是對上面已經實現了"GroovyInterceptable"介面的Foo類如下測試:

 

      Foo.metaClass.invokeMethod = {

             String name,args1 ->

               def m = Foo.metaClass.getMetaMethod(name,args1)

               def result

               if(m)

                   result = m.invoke(delegate,args1)

               else

                   result = 'test'

               result

 

      }

     

      def foo = new Foo()

     

      println foo.foo()

     

      println foo.test()

   

 

運行結果為:

invoke

invoke

 

 

從運行結果可以看出,GroovyInterceptable的"invokeMethod"方法是優先於metaClass的"invokeMethod"方法的調用的;或者說,如果一個對象同時存在GroovyInterceptable的"invokeMethod"方法和metaClass的"invokeMethod"方法,那麼系統將調用GroovyInterceptable的"invokeMethod"方法,而不管metaClass的"invokeMethod"方法。

最後,我們來做一個總結吧。對於一個對象的方法調用,如果該對象的類實現了"GroovyInterceptable"介面,那麼,系統將調用GroovyInterceptable的"invokeMethod"方法;否則,系統將調用metaClass的"invokeMethod"方法;如果該對象沒有實現metaClass的"invokeMethod"方法,那麼系統將調用對象的"invokeMethod"方法。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.