Groovy學習目錄-傳送門
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
實現,它返回配置的值或一個新的ConfigObject
實例,但永遠不為null
。
def config = new ConfigSlurper().parse('''
app.date = new Date()
app.age = 42
app.name = "Test${42}"
''')
assert config.test != null//`config.test`還沒有被指定,它被調用時返回一個`ConfigObject`。
在點符號
是配置變量名稱的一部分的情況下,可以使用單引號或雙引號對其進行轉義。
def config = new ConfigSlurper().parse('''
app."person.age" = 42
''')
assert config.app."person.age" == 42
此外,ConfigSlurper
還支持environments
。 environments
方法可以用來移交一個本身可能由幾個部分組成的Closure
實例。 假設我們想為開發環境創建一個特定的配置值。 當創建ConfigSlurper實例時,我們可以使用ConfigSlurper(String)
構造函數來指定目標環境。
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
環境不限于任何特定的環境名稱。 它只依賴于ConfigSlurper
客戶端代碼支持和解釋什么值。
environments
方法是內置的,但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
轉換為可能存儲到* .properties
文本文件的java.util.Properties
對象。 請注意,將配置值添加到新創建的Properties
實例時,將其轉換為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
類可用于創建動態可擴展對象。 盡管它的名稱叫Expando,它不使用類ExpandoMetaClass
。 每個Expando
對象表示一個獨立的動態制作的實例,可以在運行時使用屬性(或方法)進行擴展。
def expando = new Expando()
expando.name = 'John'
assert expando.name == 'John'
當動態屬性注冊Closure
代碼塊時,會發生特殊情況。 一旦Closure
被注冊,它就可以被調用,因為它將通過方法調用完成。
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。 當添加,刪除或更改元素時,每個集合都會觸發java.beans.PropertyChangeEvent
事件。 注意,PropertyChangeEvent
不僅發出某個事件已經發生的信號,此外,它保存關于屬性名稱和某個屬性已經改變到的舊/新值的信息。
根據發生的更改的類型,可觀察的集合可能觸發更專門的PropertyChangeEvent
類型。 例如,向可觀察列表中添加元素會觸發ObservableList.ElementAddedEvent
事件。
def event //聲明一個PropertyChangeEventListener捕獲被觸發的事件
def listener = {
if (it instanceof ObservableList.ElementEvent) { //ObservableList.ElementEvent及其子類型與此偵聽器相關
event = it
}
} as PropertyChangeListener
def observable = [1, 2, 3] as ObservableList //注冊監聽器
observable.addPropertyChangeListener(listener) //從給定列表創建一個ObservableList
observable.add 42 //觸發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
請注意,添加元素實際上會觸發兩個事件。 第一個是類型 ObservableList.ElementAddedEvent
,第二個是一個普通的PropertyChangeEvent
,通知監聽器屬性size
的更改。
ObservableList.ElementClearedEvent
事件類型是另一個有趣的事件類型。 每當刪除多個元素時,例如調用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
帶有我們在本節中對ObservableList
所看到的相同的概念。