文章目录
在第一讲中显示了如何使用注解配置bean,其实这是Spring3引进的特性,Spring2使用的是XML的方式来配置Bean,那时候漫天的XML文件使得Spring有着配置地狱
的称号。Spring也一直在力求改变这一缺陷。Spring3引入的注解方式确实使配置精简不少,而Spring4则引入了Groovy DSL来配置,其语法比XML要简单很多,而且Groovy本身是门语言,其配置文件就相当于代码,可以用来实现复杂的配置。
废话少说,让我们来对Groovy DSL配置来个第一次亲密接触。
首先我们先实现一个XML的bean配置,沿用第一讲中的例子。
configuration.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="movieService" class="huangbowen.net.service.DefaultMovieService"/>
<bean id="cinema" class="huangbowen.net.service.Cinema"> <property name="movieService" ref="movieService"/> </bean> </beans>
|
这个XML文件就不用我多做解释了,很清晰明了。Ok,照例写个测试来测一下。
XmlConfigurationTest.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package huangbowen.net;
import huangbowen.net.service.Cinema; import huangbowen.net.service.DefaultMovieService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"/configuration.xml"}) public class XmlConfigurationTest {
@Autowired private ApplicationContext applicationContext;
@Autowired private Cinema cinema;
@Test public void shouldGetCinemaInstance() { Cinema cinema = applicationContext.getBean(Cinema.class); assertNotNull(cinema); }
@Test public void shouldGetAutowiredCinema() { assertNotNull(cinema); }
@Test public void shouldGetMovieServiceInstance() { assertNotNull(cinema.getMovieService()); assertThat(cinema.getMovieService(), instanceOf(DefaultMovieService.class)); }
}
|
这个测试与第二讲中的测试基本上一样,不过Spring配置的读取是从configuration.xml来的,在@ContextConfiguration中指定了该xml文件为Spring配置文件。
如果想使用Groovy DSL的话第一步需要引入groovy依赖。
pom.xml1 2 3 4 5 6 7
| <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.2.2</version> </dependency>
|
然后就可以新建一个groovy文件来实现配置编写。
Configuration.groovy1 2 3 4 5 6 7 8 9
| beans {
movieService huangbowen.net.service.DefaultMovieService
cinema huangbowen.net.service.Cinema, movieService : movieService
}
|
这其实体现不出来Groovy DSL的强大灵活,因为我们的例子太简单了。
beans相当于xml中的beans标签,第一行中是 bean id + class的形式。
第二行是bean id + class + properties map的形式。第二个参数是一个map数组,分别对应property和值。
实现同样的Bean配置有很多种写法。
1 2 3 4 5
| movieService (huangbowen.net.service.DefaultMovieService)
cinema(huangbowen.net.service.Cinema, {movieService : movieService})
|
上面这种其实是Groovy语法的一个特性,在调用方法时括号是可选的,既可以加,也可以不加。
1 2 3 4 5 6 7
| movieService huangbowen.net.service.DefaultMovieService
cinema (huangbowen.net.service.Cinema) { movieService :ref movieService }
|
上面这中使用了另一个设置属性的方法,通过一个闭包将属性设置进去。
1 2 3 4 5 6 7
| movieService huangbowen.net.service.DefaultMovieService
cinema (huangbowen.net.service.Cinema) { movieService : movieService }
|
这种更好理解了,ref方法也是可选的。
来照旧写个测试来测一下。
GroovyDSLConfigurationTest.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| package huangbowen.net;
import huangbowen.net.service.Cinema; import huangbowen.net.service.DefaultMovieService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.context.ApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AbstractGenericContextLoader;
import static huangbowen.net.GroovyDSLConfigurationTest.*; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = "classpath:Configuration.groovy", loader = GenericGroovyContextLoader.class) public class GroovyDSLConfigurationTest {
public static class GenericGroovyContextLoader extends AbstractGenericContextLoader {
@Override protected BeanDefinitionReader createBeanDefinitionReader( GenericApplicationContext context) { return new GroovyBeanDefinitionReader(context); }
@Override protected String getResourceSuffix() { return ".groovy"; }
}
@Autowired private ApplicationContext applicationContext;
@Autowired private Cinema cinema;
@Test public void shouldGetCinemaInstance() { Cinema cinema = applicationContext.getBean(Cinema.class); assertNotNull(cinema); }
@Test public void shouldGetAutowiredCinema() { assertNotNull(cinema); }
@Test public void shouldGetMovieServiceInstance() { assertNotNull(cinema.getMovieService()); assertThat(cinema.getMovieService(), instanceOf(DefaultMovieService.class)); }
}
|
在集成测试中如果加载xml配置文件,Spring提供了GenericXmlContextLoader类,如果加载注解方式的配置类,Spring提供了AnnotationConfigContextLoader类。但是对于Groovy配置文件Spring testContext框架还未提供相应的Loader,所以在本测试方法中需要自己实现一个Loader,其实也简单,只要实现两个方法即可。
本例中的源码请在我的GitHub上自行下载。