Spring4 Groovy Bean定义DSL

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​​​​​​​

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值