iT邦幫忙

DAY 13
0

邊看邊學Groovy/Grails/Gradle系列 第 10

Groovy重要觀念(1)-MOP中GroovyInterceptable/TracingInterceptor

今天要跟大家分享Groovy裡面interceptor如何使用,有兩種方式可以做到before method做什麼事情或是after method做什麼事情,一則是先宣告一個class實作GroovyInterceptable,override invokeMethod,另一種是宣告TracingInterceptor,在指定給ProxyMetaClass中interceptor屬性,兩者都可以達到相同目的,只是後者Groovy幫我們減少了很多coding,若有學過Spring的AOP的話,應該會發現少了很多程式碼,不用指定pointcut, aspect等一堆....
第一種方法首先必須import org.codehaus.groovy.runtime.InvokerHelper,協助我們在runtime取得對應之metaclass,以方便操作,再來如上述宣告class實作GroovyInterceptable
,接著宣告一個dummy的class,裡面包幾個簡單的方法呼叫彼此,以測試before/after method駛後有被觸發

package intro


import org.codehaus.groovy.runtime.InvokerHelper //一定要宣告
import org.codehaus.groovy.runtime.StringBufferWriter //用來runtime時寫入log


class gInterceptor implements GroovyInterceptable {
	Writer writer=new PrintWriter(System.out)
	//override invokeMethod
    Object invokeMethod(String name, Object args){
     
	writer.write("Before Calling Method ${name}")
	writer.write("\n")
    writer.flush()
			
    def metaClass = InvokerHelper.getMetaClass(this)
	//InvokerHelp方法就是在runtime到MetaRegistry找出此class對應的metaclass
	def result = metaClass.invokeMethod(this, name, args)
	//記錄每一次呼叫方法
			
    writer.write("After Calling Method ${name}")
	writer.write("\n")
    writer.flush()
						
    return result //第一次回傳second(),第二回傳third(),直到不是方法為止
			              //並繼續執行invokeMetho內的程式碼
    }
}
	 
class subMethod extends gInterceptor {
    String first(){
        return second()
    }
	String second(){
    	return third()
	}
    String third(){
		return 'Hello! This is the last method call'
    }
}
    
def log=new StringBuffer()
def testInterceptor=new gInterceptor(writer: new StringBufferWriter(log))
def callingMethod =new subMethod()
print callingMethod.first()
    

執行結果:

Before Calling Method first
Before Calling Method second
Before Calling Method third
After Calling Method third
After Calling Method second
After Calling Method first
Hello! This is the last method call

第二種方法則需要透過Groovy特別為interceptor功能設計ProxyMetaClass,另搭配TracingInterceptor,TracingInterceptor應該可以override其中的方法,但簡單範例就已預設的實作demo,程式碼如下。

import org.codehaus.groovy.runtime.StringBufferWriter
//無須再import InvokerHelper
class proxyMethod{ //dummy的class
    String first(){
        return second()     
    } 
	String second(){
		return third()
	}
	
    String third(){
        return 'Hello! This is the last method call'
    } 
} 

def log=new StringBuffer("\n")
def gInterceptor= new TracingInterceptor() 
//new一個TracingInterceptor物件,沒有其他coding的話就是預設實作
def proxy=ProxyMetaClass.getInstance(proxyMethod.class)
//取得ProxyMetaClass物件並指定要攔截的class
proxy.interceptor =gInterceptor
//將TracingInterceptor物件實作指定給ProxyMetaClass
proxy.use{ 
	//Use語法(Category),表示呼叫proxyMethod時以proxy class處理
    new proxyMethod().first()
}
println log.toString();
print new proxyMethod().first()

執行結果如下:

before proxyMethod.ctor()
after  proxyMethod.ctor()
before proxyMethod.first()
  before proxyMethod.second()
    before proxyMethod.third()
    after  proxyMethod.third()
  after  proxyMethod.second()
after  proxyMethod.first()


Hello! This is the last method call

兩個結果不同的是TracingInterceptor還會觸發ctor()這個方法,另外其預設實作是有縮排的,比較美觀,當然interceptor不可能僅僅只能印出訊息,更多應用應該在Grails裡會提到。


上一篇
Groovy基本語法(4)-Groovy JDBC語法(4)-使用DataSet語法
下一篇
Groovy基本語法(5)-使用Builder語法(Node, XML)
系列文
邊看邊學Groovy/Grails/Gradle27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言