`
jinnianshilongnian
  • 浏览: 21505209 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418798
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008953
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639578
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259965
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597402
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250249
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5859076
Group-logo
跟我学Nginx+Lua开...
浏览量:702309
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785274
社区版块
存档分类
最新评论

Spring4新特性——Groovy Bean定义DSL

阅读更多

Spring4新特性——泛型限定式依赖注入

Spring4新特性——核心容器的其他改进

Spring4新特性——Web开发的增强

Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC 

Spring4新特性——Groovy Bean定义DSL

Spring4新特性——更好的Java泛型操作API 

Spring4新特性——JSR310日期API的支持

Spring4新特性——注解、脚本、任务、MVC等其他特性改进 

 

Spring4支持使用Groovy DSL来进行Bean定义配置,其类似于XML,不过因为是Groovy DSL,可以实现任何复杂的语法配置,但是对于配置,我们需要那么复杂吗?本着学习的态度试用了下其Groovy DSL定义Bean,其主要缺点:

1、DSL语法规则不足,需要其后续维护;

2、编辑器的代码补全需要跟进,否则没有代码补全,写这个很痛苦;

3、出错提示不友好,排错难;

4、当前对于一些配置还是需要XML的支持,所以还不是100%的纯Groovy DSL;

5、目前对整个Spring生态支持还是不够的,比如Web,需要观望。

 

其优点就是其本质是Groovy脚本,所以可以做非常复杂的配置,如果以上问题能够解决,其也是一个不错的选择。在Groovy中的话使用这种配置感觉不会有什么问题,但是在纯Java开发环境下也是有它,给我的感觉是这个功能其目的是去推广它的groovy。比较怀疑它的动机。

 

接下来我们来看看Spring配置的发展:

Spring 2时代是XML风格配置  可以参考《跟我学Spring3》的前几章

Spring 3时代引入注解风格配置  可以参考《跟我学Spring3》的第12章 

Spring 4时代引入Groovy DSL风格来配置 后续讲解

 

一、对比

对于我来说,没有哪个好/坏,只有适用不适用;开发方便不方便。接下来我们来看一下各种类型的配置吧:

XML风格配置

    <context:component-scan base-package="com.sishuok.spring4"/>
    <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
        <property name="validator" ref="validator"/>
    </bean>
    <mvc:annotation-driven validator="validator"/>

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
        <property name="validationMessageSource" ref="messageSource"/>
    </bean>

 

注解风格配置 

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.sishuok.spring4")
public class MvcConfiguration extends WebMvcConfigurationSupport {
    @Override
    protected Validator getValidator() {
        LocalValidatorFactoryBean localValidatorFactoryBean =
                new LocalValidatorFactoryBean();
        localValidatorFactoryBean.setProviderClass(HibernateValidator.class);
        localValidatorFactoryBean.setValidationMessageSource(messageSource());
        return localValidatorFactoryBean;
    }
}

 

Groovy DSL风格配置

import org.hibernate.validator.HibernateValidator
import org.springframework.context.support.ReloadableResourceBundleMessageSource
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean

beans {
    xmlns context: "http://www.springframework.org/schema/context"
    xmlns mvc: "http://www.springframework.org/schema/mvc"

    context.'component-scan'('base-package': "com,sishuok.spring4")
    mvc.'annotation-driven'('validator': "validator")

    validator(LocalValidatorFactoryBean) {
        providerClass = HibernateValidator.class
        validationMessageSource = ref("messageSource")
    }
}

因为Spring4 webmvc没有提供用于Web环境的Groovy DSL实现的WebApplicationContext,所以为了在web环境使用,单独写了一个WebGenricGroovyApplicationContext,可以到源码中查找。

 

 

可以看到,它们之前差别不是特别大;以上只提取了部分配置,完整的配置可以参考我的github:spring4-showcase

 

对于注解风格的配置,如果在Servlet3容器中使用的话,可以借助WebApplicationInitializer实现无配置:

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(javax.servlet.ServletContext sc) throws ServletException {

//        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
//        rootContext.register(AppConfig.class);
//        sc.addListener(new ContextLoaderListener(rootContext));

        //2、springmvc上下文
        AnnotationConfigWebApplicationContext springMvcContext = new AnnotationConfigWebApplicationContext();
        springMvcContext.register(MvcConfiguration.class);

        //3、DispatcherServlet
        DispatcherServlet dispatcherServlet = new DispatcherServlet(springMvcContext);
        ServletRegistration.Dynamic dynamic = sc.addServlet("dispatcherServlet", dispatcherServlet);
        dynamic.setLoadOnStartup(1);
        dynamic.addMapping("/");

        //4、CharacterEncodingFilter
        FilterRegistration filterRegistration =
                sc.addFilter("characterEncodingFilter", CharacterEncodingFilter.class);
        filterRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");


    }
}

 

到底好还是不好,需要根据自己项目大小等一些因素来衡量。对于Servlet3可以参考我github的示例:servlet3-showcase  

 

对于Groovy风格配置,如果语法足够丰富、Spring内部支持完善,且编辑器支持也非常好的话,也是不错的选择。

 

 

二、Groovy Bean定义

接下来我们来看下groovy DSL的具体使用吧:

1、安装环境

        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>${groovy.version}</version>
        </dependency>

我使用的groovy版本是2.2.1

 

2、相关组件类

此处使用Spring Framework官网的hello world,可以前往http://projects.spring.io/spring-framework/ 主页查看 

 

3、Groovy Bean定义配置文件

import com.sishuok.spring4.xml.MessageServiceImpl
import com.sishuok.spring4.xml.MessagePrinter

beans {
    messageService(MessageServiceImpl) {//名字(类型) 
        message = "hello"  //注入的属性
    }

    messagePrinter(MessagePrinter, messageService) //名字(类型,构造器参数列表)

}

从此处可以看到 如果仅仅是简单的Bean定义,确实比XML简洁。

 

 

4、测试

如果不测试环境可以这样测试:

public class XmlGroovyBeanDefinitionTest1 {
    @Test
    public void test() {
        ApplicationContext ctx = new GenericGroovyApplicationContext("classpath:spring-config-xml.groovy");
        MessagePrinter messagePrinter = (MessagePrinter) ctx.getBean("messagePrinter");
        messagePrinter.printMessage();
    }
}

使用GenericGroovyApplicationContext加载groovy配置文件。 

 

 

如果想集成到Spring Test中,可以这样:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-config-xml.groovy", loader = GenericGroovyContextLoader.class)
public class XmlGroovyBeanDefinitionTest2 {

    @Autowired
    private MessagePrinter messagePrinter;

    @Test
    public void test() {
        messagePrinter.printMessage();
    }
}

此处需要定义我们自己的bean loader,即从groovy配置文件加载:

public class GenericGroovyContextLoader extends AbstractGenericContextLoader {

    @Override
    protected String getResourceSuffix() {
        throw new UnsupportedOperationException(
                "GenericGroovyContextLoader does not support the getResourceSuffix() method");
    }
    @Override
    protected BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context) {
        return new GroovyBeanDefinitionReader(context);
    }
}

使用GroovyBeanDefinitionReader来加载groovy配置文件。  

 

到此基本的使用就结束了,还算是比较简洁,但是我们已经注意到了,在纯Java环境做测试还是比较麻烦的。 比如没有给我们写好相关的测试支撑类。另外大家可以前往Spring的github看看在groovy中的单元测试:GroovyBeanDefinitionReaderTests.groovy

 

再看一下我们使用注解方式呢:

@Component
public class MessageServiceImpl implements MessageService {
    @Autowired
    @Qualifier("message")
    private String message;
    ……
}
 
@Component
public class MessagePrinter {
    private MessageService messageService;
    @Autowired
    public MessagePrinter(MessageService messageService) {
        this.messageService = messageService;
    }
……
}

 

此处省略无关代码,需要的话直接去github查看 。点击前往 

 

Groovy配置文件:

 

beans {
    xmlns context: "http://www.springframework.org/schema/context"    //导入命名空间

    context.'component-scan'('base-package': "com.sishuok.spring4") {
        'exclude-filter'('type': "aspectj", 'expression': "com.sishuok.spring4.xml.*")
    }

    message(String, "hello") {}

}
在该配置文件中支持导入xml命名空间, 其中context.'component-scan'部分等价于XML中的:
    <context:component-scan base-package="com.sishuok.spring4">
        <context:exclude-filter type="aspectj" expression="com.sishuok.spring4.xml.*"/>
    </context:component-scan>            
 从这里可以看出,其还没能完全从XML风格配置中走出来,不是纯Groovy DSL。

 

 

测试方式和之前的一样就不重复了,可以查看XmlGroovyBeanDefinitionTest2.java

 

三、Groovy Bean定义 DSL语法

到目前为止,基本的helloworld就搞定了;接下来看看Groovy DSL都支持哪些配置吧:

创建Bean

 

构造器

    validator(LocalValidatorFactoryBean) { //名字(类型)
        providerClass = HibernateValidator.class  //属性=值
        validationMessageSource = ref("messageSource") //属性 = 引用,当然也支持如 validationMessageSource=messageSource 但是这种方式缺点是messageSource必须在validator之前声明
    } 

静态工厂方法

def bean = factory(StaticFactory) {
    prop = 1
}
bean.factoryMethod = "getInstance"
或者
bean(StaticFactory) { bean ->
    bean.factoryMethod = "getInstance"
    prop = 1
}
 
实例工厂方法
beanFactory(Factory)
bean(beanFactory : "newInstance", "args") {
    prop = 1
}
或者
beanFactory(Factory)
bean("bean"){bean ->
    bean.factoryBean="beanFactory"
    bean.factoryMethod="newInstance"
    prop = 1
}

 

依赖注入

 

属性注入

    beanName(BeanClass) { //名字(类型)
        str = "123" // 常量直接注入
        bean = ref("bean") //属性 = 引用 ref("bean", true) 这样的话是引用父容器的
        beans = [bean1, bean2] //数组/集合
        props = [key1:"value1", key2:"value2"] // Properties / Map
    }

 

构造器注入 

bean(Bean, "args1", "args2") 

 

静态工厂注入/实例工厂注入,请参考创建bean部分

 

 

匿名内部Bean

outer(OuterBean) {
   prop = 1
   inner =  { InnerBean bean ->  //匿名内部Bean
                          prop =2
            }
}
outer(OuterBean) {
   prop = 1
   inner =  { bean ->  //匿名内部Bean 通过实例工厂方法创建
                          bean.factoryBean = "innerBean"
                          bean.factoryMethod = "create"
                          prop = 2
            }
}

单例/非单例/作用域

singletonBean(Bean1) { bean ->
    bean.singleton = true
}
nonSingletonBean(Bean1) { bean ->
    bean.singleton = false
}
prototypeBean(Bean1) { bean ->
    bean.scope = "prototype"
}

 

其中bean可以理解为xml中的<bean> 标签,即bean定义。

 

 

父子Bean

parent(Bean1){ bean -> 
    bean.'abstract' = true //抽象的
    prop = 123
}
child { bean ->
    bean.parent = parent //指定父bean
}
 

 

命名空间

    xmlns aop:"http://www.springframework.org/schema/aop"
    myAspect(MyAspect)
    aop {
        config("proxy-target-class":true) {
            aspect( id:"test",ref:"myAspect" ) {
                before method:"before", pointcut: "execution(void com.sishuok.spring4..*.*(..))"
            }
        }
    }
以上是AOP的,可以自己推到其他相关的配置; 

 

    xmlns context: "http://www.springframework.org/schema/context"   
    context.'component-scan'('base-package': "com.sishuok.spring4") {
        'exclude-filter'('type': "aspectj", 'expression': "com.sishuok.spring4.xml.*")
    }
以上是component-scan,之前介绍过了。

  

xmlns aop:"http://www.springframework.org/schema/aop"
scopedList(ArrayList) { bean ->
    bean.scope = "haha"
    aop.'scoped-proxy'()  
}
 等价于
    <bean id="scopedList" class="java.util.ArrayList" scope="haha">
        <aop:scoped-proxy/>
    </bean>

 

    xmlns util:"http://www.springframework.org/schema/util"
    util.list(id : 'list') {
        value 1
        value 2
    }
等价于XML:
    <util:list id="list">
        <value>1</value>
        <value>2</value>
    </util:list>

 

    xmlns util:"http://www.springframework.org/schema/util"
    util.map(id : 'map') {
        entry(key : 1, value :1)
        entry('key-ref' : "messageService", 'value-ref' : "messageService")
    }
 等价于
    <util:map id="map">
        <entry key="1" value="1"/>
        <entry key-ref="messageService" value-ref="messageService"/>
    </util:map>

引入其他配置文件

importBeans "classpath:org/springframework/context/groovy/test.xml"
当然也能引入XML的。 

 

对于DSL新的更新大家可以关注:GroovyBeanDefinitionReaderTests.groovy,本文也是根据其编写的。

 

再来看看groovy bean定义的另一个好处:

我们可以直接在groovy bean定义文件中声明类,然后使用

@Controller
def class GroovyController {
    @RequestMapping("/groovy")
    @ResponseBody
    public String hello() {
        return "hello";
    }
}

beans {

    groovyController(GroovyController)

}

 

 另一种Spring很早就支持的方式是引入外部groovy文件,如:

xmlns lang: "http://www.springframework.org/schema/lang"
lang.'groovy'(id: 'groovyController2', 'script-source': 'classpath:com/sishuok/spring4/controller/GroovyController2.groovy')

使用其lang命名空间引入外部脚本文件。

 

 

到此,Groovy Bean定义DSL就介绍完了,其没有什么特别之处,只是换了种写法而已,我认为目前试试即可,还不能用到真实环境。

 

 

示例代码:

https://github.com/zhangkaitao/spring4-showcase

https://github.com/zhangkaitao/servlet3-showcase

 

 

 

13
1
分享到:
评论
4 楼 jinnianshilongnian 2013-12-19  
hantsy 写道
my post about Spring groovy dsl bean definition.
http://my.oschina.net/hantsy/blog/184643

哈哈,你够快的,我昨天晚上把它的测试用例挨着跑了一遍,把相关语法给摘出来了
3 楼 hantsy 2013-12-19  
my post about Spring groovy dsl bean definition.
http://my.oschina.net/hantsy/blog/184643
2 楼 jinnianshilongnian 2013-12-19  
Credo 写道
大牛啊,现在看spring都只往你blog跑了.........

偶不是什么大神 
1 楼 Credo 2013-12-19  
大牛啊,现在看spring都只往你blog跑了.........

相关推荐

    Spring4.X最新帮助文档带视图结构树的

    - **Groovy Bean Definition DSL(Groovy Bean Definition DSL):** 使用Groovy语言定义Bean配置。 - **核心容器改进(Core Container Improvements):** 在核心容器方面进行了一系列改进,提升了性能和易用性。 - ...

    SpringFramework4

    Groovy Bean Definition DSL(领域特定语言)的引入是Spring Framework 4.x中的一项创新,它允许开发者使用Groovy语言来配置Spring beans,这样做的好处是语法更加简洁,配置更加直观。 Spring Framework 4.x版本对...

    spring4 英文文档

    II章节“Whats New in Spring Framework 4.x”探讨了Spring 4.x版本中的新特性,比如对于Java 8、Java EE 6/7的支持,以及Groovy Bean定义DSL,这些新特性使得Spring框架更加现代化,更易于集成当前最新的技术栈。...

    Spring4开发手册(开发指南)

    同时,文档还提到了 Groovy Bean 定义DSL,核心容器改进,通用Web功能改进,WebSocket、SockJS和STOMP消息传递支持,以及测试功能的增强。 7. 核心技术部分着重介绍了Spring的控制反转(IoC)容器。文档首先讲解了...

    spring framewok 4参考文档

    此外,该版本还增加了对Groovy Bean Definition DSL的支持,简化了Spring配置。 对于核心容器的改进,包括了对常规Web应用的增强,以及引入了WebSocket、SockJS和STOMP消息处理的支持,这些新特性对于构建现代的、...

    workshop-spring-4.0-to-4.2:Spring 4新功能研讨会

    从Spring Framework 4.0开始,可以使用Groovy DSL定义外部bean配置。 这在概念上与使用XML bean定义相似,但是允许使用更简洁的语法。 使用Groovy还使您可以轻松地将bean定义直接嵌入到引导代码中。 类固醇上的XML...

    Spring Reference Core Technologies

    - **Groovy Bean Definition DSL**:Spring支持使用Groovy语言编写配置脚本来定义bean,这种方式更加灵活且易于维护。 - **1.2.2 实例化容器** 实例化IoC容器是使用Spring框架的第一步。可以通过`...

    spring4 api

    ### Spring4 API 相关知识点 #### 一、Spring Framework 概览 ...以上是Spring4 API的关键知识点总结,这些内容覆盖了Spring框架的基础概念、新特性及核心技术等方面。对于学习Spring的人来说,理解这些内容至关重要。

    spring 4.10官方文档

    5. 新特性介绍:在Spring Framework 4.0中引入的新特性,包括改进的入门体验、移除过时的包和方法、对Java 8以及Java EE 6和7的支持、Groovy Bean定义DSL、核心容器的改进、通用Web功能的提升、WebSocket、SockJS...

    spring4 参考手册官方文档(英文)

    - 3.NewFeaturesandEnhancementsinSpringFramework4.0:概括了Spring 4.0版本中新增的功能和改进,包括改进的入门体验、移除已过时的包和方法、支持Java 8以及对Java EE 6和7的支持、Groovy Bean定义DSL、核心容器...

    spring core官方文档.pdf

    - **Groovy Bean Definition DSL**:提供了更简洁的配置方式,利用Groovy语言编写Bean定义。 - **容器的使用** - 在了解了如何配置容器之后,接下来是学习如何在应用程序中使用这些配置好的容器。 #### 二、Bean...

    spring-framework-reference-4.pdf

    Spring 4.0引入了使用Groovy语言编写的Bean定义DSL(领域特定语言),简化了基于Spring的应用配置。 3.6 核心容器的改进 核心容器模块得到了增强,提高了配置和使用上的灵活性。 3.7 通用Web改进 Spring 4.x增强了...

    pring4新特性之核心部分共7页.pdf.zip

    《Spring4新特性之核心部分》是一份详细探讨Spring4框架新特性的文档,总共包含7页内容。作为Java开发领域的重要组件,Spring框架的每次更新都为开发者带来了诸多改进和创新。Spring4版本尤其注重性能提升、API优化...

    spring-framework-4-reference

    另外,新增了对Java EE 6和Java EE 7的支持,并引入了Groovy Bean Definition DSL,使得使用Groovy语言定义bean更加方便。核心容器的改进,如增加了新的注解,改进了bean的初始化和销毁过程。常规Web应用也得到了...

    spring4 文档

    同时,Groovy Bean Definition DSL的引入简化了Spring应用的配置。核心容器、Web模块、WebSocket、SockJS和STOMP消息支持等方面都有所改进。 4.1版本继续增强WebSocket和STOMP消息功能。4.2版本则集中于测试改进、...

    spring-framework-reference

    新版本还引入了Groovy Bean定义DSL,进一步提高了核心容器的改进,如改进的Web支持、WebSocket、SockJS和STOMP消息传递以及测试改进。 三、核心技术 文档详细介绍了Spring框架的核心技术,特别是控制反转(IoC)...

    Spring Framework 4.1.0参考文档

    - Groovy Bean定义DSL:允许使用Groovy脚本来定义Spring bean,简化配置。 - 核心容器改进:提高了核心容器的性能和灵活性。 - Web功能改进:增加了对WebSocket、SockJS和STOMP消息传递的支持。 - 测试改进:为了...

    最新spring官网文档英文(4.3.0.RC1)

    Groovy Bean Definition DSL是一种使用Groovy语言定义Spring Bean的新方法,使得配置更加简洁和灵活。 **3.6 核心容器改进** 对Spring的核心容器进行了优化,提高了性能并增强了功能性。 **3.7 Web改进** 对Web...

    spring4 中文API

    根据提供的信息,我们可以深入探讨Spring 4框架的相关知识点,包括其新特性、核心技术和关键概念。下面将逐一解析这些内容。 ### Spring Framework 总览 #### 开始与介绍 Spring Framework是一个开源的应用程序...

    Spring Framework 4.0 Documentation

    在Spring Framework 4.x的新特性中,文档突出了Java 8、Java EE 6和Java EE 7的支持,Groovy Bean定义DSL的引入,以及核心容器、Web层、WebSocket、SockJS和STOMP消息传递的改进。测试模块也得到了增强,为开发人员...

Global site tag (gtag.js) - Google Analytics