Groovy學(xué)習(xí)目錄-傳送門
ConfigSlurper
ConfigSlurper是一個用于讀取以Groovy腳本形式定義的配置文件的實用程序類。 類似于Java * .properties文件的情況,ConfigSlurper允許使用點符號。 但此外,它允許Closure作用域配置值和任意對象類型。
def config = new ConfigSlurper().parse('''
app.date = new Date() //點符號的用法
app.age = 42
app { //使用Closure作用域作為點符號的替代
name = "Test${42}"
}
''')
assert config.app.date instanceof Date
assert config.app.age == 42
assert config.app.name == 'Test42'
從上面的例子可以看出,parse方法可以用來檢索groovy.util.ConfigObject實例。ConfigObject是一個專門的java.util.Map實現(xiàn),它返回配置的值或一個新的ConfigObject實例,但永遠不為null。
def config = new ConfigSlurper().parse('''
app.date = new Date()
app.age = 42
app.name = "Test${42}"
''')
assert config.test != null//`config.test`還沒有被指定,它被調(diào)用時返回一個`ConfigObject`。
在點符號是配置變量名稱的一部分的情況下,可以使用單引號或雙引號對其進行轉(zhuǎn)義。
def config = new ConfigSlurper().parse('''
app."person.age" = 42
''')
assert config.app."person.age" == 42
此外,ConfigSlurper還支持environments。 environments方法可以用來移交一個本身可能由幾個部分組成的Closure實例。 假設(shè)我們想為開發(fā)環(huán)境創(chuàng)建一個特定的配置值。 當(dāng)創(chuàng)建ConfigSlurper實例時,我們可以使用ConfigSlurper(String)構(gòu)造函數(shù)來指定目標(biāo)環(huán)境。
def config = new ConfigSlurper('development').parse('''
environments {
development {
app.port = 8080
}
test {
app.port = 8082
}
production {
app.port = 80
}
}
''')
assert config.app.port == 8080
ConfigSlurper環(huán)境不限于任何特定的環(huán)境名稱。 它只依賴于ConfigSlurper客戶端代碼支持和解釋什么值。
environments方法是內(nèi)置的,但registerConditionalBlock方法可用于注冊除environments名稱之外的其他方法名稱。
def slurper = new ConfigSlurper()
slurper.registerConditionalBlock('myProject', 'developers') //一旦新block被注冊,ConfigSlurper可以解析它。
def config = slurper.parse('''
sendMail = true
myProject {
developers {
sendMail = false
}
}
''')
assert !config.sendMail
對于Java集成,toProperties方法可用于將ConfigObject轉(zhuǎn)換為可能存儲到* .properties文本文件的java.util.Properties對象。 請注意,將配置值添加到新創(chuàng)建的Properties實例時,將其轉(zhuǎn)換為String實例。
def config = new ConfigSlurper().parse('''
app.date = new Date()
app.age = 42
app {
name = "Test${42}"
}
''')
def properties = config.toProperties()
assert properties."app.date" instanceof String
assert properties."app.age" == '42'
assert properties."app.name" == 'Test42'
Expando
Expando類可用于創(chuàng)建動態(tài)可擴展對象。 盡管它的名稱叫Expando,它不使用類ExpandoMetaClass。 每個Expando對象表示一個獨立的動態(tài)制作的實例,可以在運行時使用屬性(或方法)進行擴展。
def expando = new Expando()
expando.name = 'John'
assert expando.name == 'John'
當(dāng)動態(tài)屬性注冊Closure代碼塊時,會發(fā)生特殊情況。 一旦Closure被注冊,它就可以被調(diào)用,因為它將通過方法調(diào)用完成。
def expando = new Expando()
expando.toString = { -> 'John' }
expando.say = { String s -> "John says: ${s}" }
assert expando as String == 'John'
assert expando.say('Hi') == 'John says: Hi'
可觀察的 list, map and set
Groovy帶有可觀察的 list, map and set。 當(dāng)添加,刪除或更改元素時,每個集合都會觸發(fā)java.beans.PropertyChangeEvent事件。 注意,PropertyChangeEvent不僅發(fā)出某個事件已經(jīng)發(fā)生的信號,此外,它保存關(guān)于屬性名稱和某個屬性已經(jīng)改變到的舊/新值的信息。
根據(jù)發(fā)生的更改的類型,可觀察的集合可能觸發(fā)更專門的PropertyChangeEvent類型。 例如,向可觀察列表中添加元素會觸發(fā)ObservableList.ElementAddedEvent事件。
def event //聲明一個PropertyChangeEventListener捕獲被觸發(fā)的事件
def listener = {
if (it instanceof ObservableList.ElementEvent) { //ObservableList.ElementEvent及其子類型與此偵聽器相關(guān)
event = it
}
} as PropertyChangeListener
def observable = [1, 2, 3] as ObservableList //注冊監(jiān)聽器
observable.addPropertyChangeListener(listener) //從給定列表創(chuàng)建一個ObservableList
observable.add 42 //觸發(fā)ObservableList.ElementAddedEvent事件
assert event instanceof ObservableList.ElementAddedEvent
def elementAddedEvent = event as ObservableList.ElementAddedEvent
assert elementAddedEvent.changeType == ObservableList.ChangeType.ADDED
assert elementAddedEvent.index == 3
assert elementAddedEvent.oldValue == null
assert elementAddedEvent.newValue == 42
請注意,添加元素實際上會觸發(fā)兩個事件。 第一個是類型 ObservableList.ElementAddedEvent,第二個是一個普通的PropertyChangeEvent,通知監(jiān)聽器屬性size的更改。
ObservableList.ElementClearedEvent事件類型是另一個有趣的事件類型。 每當(dāng)刪除多個元素時,例如調(diào)用clear()時,它保存從列表中刪除的元素。
def event
def listener = {
if (it instanceof ObservableList.ElementEvent) {
event = it
}
} as PropertyChangeListener
def observable = [1, 2, 3] as ObservableList
observable.addPropertyChangeListener(listener)
observable.clear()
assert event instanceof ObservableList.ElementClearedEvent
def elementClearedEvent = event as ObservableList.ElementClearedEvent
assert elementClearedEvent.values == [1, 2, 3]
assert observable.size() == 0
為了獲得所有支持的事件類型的概述,我們鼓勵讀者查看JavaDoc文檔或正在使用的observable集合的源代碼。
ObservableMap和ObservableSet帶有我們在本節(jié)中對ObservableList所看到的相同的概念。