Spring4支持使用Groovy DSL(Domain Specific Language)来进行Bean定义配置,其类似于XML.
Groovy不是特定领域的语言(DSL), 而是通用的语言,但Groovy却对编写出一个全新的DSL提供了良好的支持.
Groovy官方已经发布了较多基于Groovy书写的DSL.
例子:
1.目标
实现一种使用Groovy语法书写, 用于构建HTML的简单DSL,如下:
html {
head {
meta {
}
}
body {
table (style:'margin:5px;') {
tr ('class':'trClass', style:'padding:5px;') {
td {'Cell1'}
td {'Cell2'}
td {'Cell3'}
}
}
}
具体怎么实现能够通过一段DSL代码输出原始的HTML呢?主要基于Groovy的以下几个特性:
(1) Groovy脚本,不用定义class
(2) Groovy的invokeMethod方法,方法可以不书写(), 末尾省略分号, 不书写return
代码分析:
meta {
}
//这段代码的含义为:调用 meta方法,参数为一个闭包,闭包不执行任何代码。
table (style:'margin:5px;') {
}
//这段代码的含义为:调用 table方法,第一个参数为 Map,第二个参数为闭包。
tr ('class':'trClass', style:'padding:5px;') {
td {'Cell1'}
td {'Cell2'}
td {'Cell3'}
}
//这段代码的含义为:
//调用 tr方法,第一个参数为 Map,第二个参数为闭包。
//闭包中,调用了 3 个 td方法,参数都为一个闭包;闭包中直接返回了一个字符串。
代码实现
def invokeMethod(String name, args) {
print "<${name}"
args.each { arg ->
if (arg instanceof Map) {
arg.each {
print " ${it.key} ='${it.value}' "
}
} else if (arg instanceof Closure) {
print '>'
arg.delegate = this
def value = arg.call()
if (value) {
print "${value}"
}
}
}
println "</${name}>"
}
Spring配置的发展:
- Spring2是XML风格的配置
- Spring3引入注解风格配置
- spring4引入Groovy DSL风格来配置
1.Groovy Bean定义配置
beans {
messageService(MessageServiceImpl) {//名字(类型)
message = "hello" //注入的属性
}
messagePrinter(MessagePrinter, messageService) //名字(类型,构造器参数列表)
}
构造器
validator(LocalValidatorFactoryBean) { //名字(类型)
providerClass = HibernateValidator.class //属性=值
validationMessageSource = ref("messageSource") //属性 = 引用,当然也支持如 validationMessageSource=messageSource 但是这种方式缺点是messageSource必须在validator之前声明
}
属性注入
beanName(BeanClass) { //名字(类型)
str = "123" // 常量直接注入
bean = ref("bean") //属性 = 引用 ref("bean", true) 这样的话是引用父容器的
beans = [bean1, bean2] //数组/集合
props = [key1:"value1", key2:"value2"] // Properties / Map
}
单例/非单例/作用域
singletonBean(Bean1) { bean ->
bean.singleton = true
}
nonSingletonBean(Bean1) { bean ->
bean.singleton = false
}
prototypeBean(Bean1) { bean ->
bean.scope = "prototype"
}
父子bean
parent(Bean1){ bean ->
bean.'abstract' = true //抽象的
prop = 123
}
child { bean ->
bean.parent = parent //指定父bean
}
我们可以直接在groovy bean定义文件中声明类, 然后使用
@Controller
def class GroovyController {
@RequestMapping("/groovy")
@ResponseBody
public String hello() {
return "hello";
}
}
beans {
groovyController(GroovyController)
}
最后欢迎大家访问我的个人网站:1024s